public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [PATCH 00/45] Add capsule update and recovery sample.
@ 2016-09-21  6:44 Jiewen Yao
  2016-09-21  6:44 ` [PATCH 01/45] MdeModulePkg/Include: Add EDKII system FMP capsule header Jiewen Yao
                   ` (48 more replies)
  0 siblings, 49 replies; 83+ messages in thread
From: Jiewen Yao @ 2016-09-21  6:44 UTC (permalink / raw)
  To: edk2-devel
  Cc: Feng Tian, Star Zeng, Michael D Kinney, Liming Gao, Chao Zhang,
	Jeff Fan

This series patch provides sample on how to do signed capsule update
and recovery in EDKII.

This series patch is also checked into git@github.com:jyao1/edk2.git.

The feature includes:
1) Define EDKII signed system BIOS capsule format.
2) Provide EDKII signed system BIOS update sample.
3) Provide EDKII signed recovery sample.
4) Provide Microcode update sample for X86 system.
5) Update Quark to use new capsule/recovery solution.
6) Update Vlv2(MinnowMax) to use new capsule/recovery solution.

The signed capsule/recovery solution is in MdeModulePkg.
The capsule in IntelFrameworkModulePkg is deprecated.
The Microcode update solution is in UefiCpuPkg.

Cc: Feng Tian <feng.tian@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Chao Zhang <chao.b.zhang@intel.com>
Cc: Jeff Fan <jeff.fan@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>


Jiewen Yao (45):
  MdeModulePkg/Include: Add EDKII system FMP capsule header.
  MdeModulePkg/Include: Add EdkiiSystemCapsuleLib definition.
  MdeModulePkg/Include: Add FmpAuthenticationLib header.
  MdeModulePkg/Include: Add IniParsingLib header.
  MdeModulePkg/Include: Add PlatformFlashAccessLib header.
  MdeModulePkg/CapsuleLib: Add ProcessCapsules() API.
  MdeModulePkg/MdeModulePkg.dec: Add capsule related definition.
  MdeModulePkg/IniParsingLib: Add InitParsingLib instance.
  MdeModulePkg/FmpAuthenticationLib: Add FmpAuthenticationLib instance.
  MdeModulePkg/DxeCapsuleLibFmp: Add DxeCapsuleLibFmp instance.
  MdeModulePkg/DxeCapsuleLibNull: Add ProcessCapsules() interface.
  MdeModulePkg/EdkiiSystemCapsuleLib: Add EdkiiSystemCapsuleLib
    instance.
  MdeModulePkg/PlatformFlashAccessLib: Add NULL PlatformFlashAccessLib.
  MdeModulePkg/Esrt: Add ESRT_FW_TYPE_SYSTEMFIRMWARE check.
  MdeModulePkg/SystemBiosUpdate: Add SystemBiosUpdate component.
  MdeModulePkg/RecoveryModuleLoadPei: Add RecoveryModuleLoadPei.
  MdeModulePkg/CapsuleApp: Add CapsuleApp application.
  MdeModulePkg/MdeModulePkg.dsc: Add capsule related component.
  IntelFrameworkModulePkg/DxeCapsuleLib: Add ProcessCapsules()
    interface.
  SecurityPkg/SecurityPkg.dec: Add PcdPkcs7CertBuffer PCD.
  SecurityPkg/FmpAuthenticationPkcs7Lib: Add PKCS7 NULL class for FMP.
  SecurityPkg/FmpAuthenticationRsa2048Sha256Lib: Add NULL class for FMP.
  SecurityPkg/SecurityPkg.dsc: Add FmpAuthentication*Lib.
  UefiCpuPkg/Include: Add Microcode FMP definition.
  UefiCpuPkg/Include: Add MicrocodeFlashAccessLib header.
  UefiCpuPkg/UefiCpuPkg.dec: Add Microcode capsule related definition.
  UefiCpuPkg/MicrocodeUpdate: Add MicrocodeUpdate component.
  UefiCpuPkg/MicrocodeFlashAccessLib: Add NULL MicrocodeFlashAccessLib.
  UefiCpuPkg/MicrocodeCapsuleApp: Add MicrocodeCapsuleApp application.
  UefiCpuPkg/UefiCpuPkg.dsc: Add MicrocodeCapsule related component.
  QuarkPlatformPkg/PlatformFlashAccessLib: Add instance for capsule
    update.
  QuarkPlatformPkg/SystemBiosDescriptor: Add Descriptor for capsule
    update.
  QuarkPlatformPkg/SystemBiosUpdateConfig: Add capsule config file.
  QuarkPlatformPkg/PlatformInit: Remove recovery PPI installation.
  QuarkPlatformPkg/PlatformBootManager: Add capsule/recovery handling.
  QuarkPlatformPkg/dsc/fdf: Add capsule/recovery support.
  QuarkPlatformPkg/dsc/fdf: add capsule generation DSC/FDF.
  Vlv2TbltDevicePkg/PlatformFlashAccessLib: Add instance for capsule
    update.
  Vlv2TbltDevicePkg/SystemBiosDescriptor: Add Descriptor for capsule
    update.
  Vlv2TbltDevicePkg/SystemBiosUpdateConfig: Add capsule config file.
  Vlv2TbltDevicePkg/FlashDeviceLib: Add DXE flash device lib.
  Vlv2TbltDevicePkg/PlatformBootManager: Add capsule/recovery handling.
  Vlv2TbltDevicePkg/dsc/fdf: Add capsule/recovery support.
  Vlv2TbltDevicePkg/dsc/fdf: add capsule generation DSC/FDF.
  Vlv2TbltDevicePkg/bat: add capsule generation in bat.

 IntelFrameworkModulePkg/Library/DxeCapsuleLib/DxeCapsuleLib.c                                 |   39 +-
 MdeModulePkg/Application/CapsuleApp/AppSupport.c                                              |  480 ++++++
 MdeModulePkg/Application/CapsuleApp/CapsuleApp.c                                              | 1047 +++++++++++++
 MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf                                            |   71 +
 MdeModulePkg/Application/CapsuleApp/CapsuleApp.uni                                            |   22 +
 MdeModulePkg/Application/CapsuleApp/CapsuleAppExtra.uni                                       |   19 +
 MdeModulePkg/Application/CapsuleApp/CapsuleDump.c                                             |  840 +++++++++++
 MdeModulePkg/Include/Guid/EdkiiSystemFmpCapsule.h                                             |  110 ++
 MdeModulePkg/Include/Library/CapsuleLib.h                                                     |   45 +-
 MdeModulePkg/Include/Library/EdkiiSystemCapsuleLib.h                                          |  152 ++
 MdeModulePkg/Include/Library/FmpAuthenticationLib.h                                           |   91 ++
 MdeModulePkg/Include/Library/IniParsingLib.h                                                  |  153 ++
 MdeModulePkg/Include/Library/PlatformFlashAccessLib.h                                         |   59 +
 MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.c                                         | 1538 ++++++++++++++++++++
 MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.inf                                       |   82 ++
 MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.uni                                       |   22 +
 MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleProcessLib.c                                  |  517 +++++++
 MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleReportLib.c                                   |  447 ++++++
 MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleRuntime.c                                     |  112 ++
 MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf                                |   85 ++
 MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.uni                                |   22 +
 MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.c                                    |   47 +-
 MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.c                            |  609 ++++++++
 MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.inf                          |   55 +
 MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.uni                          |   22 +
 MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.c                              |  274 ++++
 MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.inf                            |   47 +
 MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.uni                            |   22 +
 MdeModulePkg/Library/IniParsingLib/IniParsingLib.c                                            | 1053 ++++++++++++++
 MdeModulePkg/Library/IniParsingLib/IniParsingLib.inf                                          |   42 +
 MdeModulePkg/Library/IniParsingLib/IniParsingLib.uni                                          |   22 +
 MdeModulePkg/Library/PlatformFlashAccessLibNull/PlatformFlashAccessLibNull.c                  |   54 +
 MdeModulePkg/Library/PlatformFlashAccessLibNull/PlatformFlashAccessLibNull.inf                |   40 +
 MdeModulePkg/Library/PlatformFlashAccessLibNull/PlatformFlashAccessLibNull.uni                |   21 +
 MdeModulePkg/MdeModulePkg.dec                                                                 |  106 ++
 MdeModulePkg/MdeModulePkg.dsc                                                                 |   24 +
 MdeModulePkg/Universal/EsrtDxe/EsrtDxe.inf                                                    |    3 +-
 MdeModulePkg/Universal/EsrtDxe/EsrtImpl.c                                                     |   37 +-
 MdeModulePkg/Universal/RecoveryModuleLoadPei/ParseConfigProfile.c                             |  158 ++
 MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPei.c                          |  746 ++++++++++
 MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPei.h                          |   44 +
 MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPei.inf                        |   71 +
 MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPei.uni                        |   21 +
 MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPeiExtra.uni                   |   20 +
 MdeModulePkg/Universal/SystemBiosUpdate/ParseConfigProfile.c                                  |  219 +++
 MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosDxe.h                                       |  393 +++++
 MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosMainDxe.c                                   |  484 ++++++
 MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosMainSetImage.c                              |  453 ++++++
 MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosMainSetImageDummy.c                         |   90 ++
 MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxe.inf                               |   66 +
 MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxe.uni                               |   21 +
 MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxeExtra.uni                          |   20 +
 MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxe.inf                               |   70 +
 MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxe.uni                               |   21 +
 MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxeExtra.uni                          |   20 +
 QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLibDxe.c   |  200 +++
 QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLibDxe.inf |   52 +
 QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/SpiFlashDevice.c              |  336 +++++
 QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/SpiFlashDevice.h              |  186 +++
 QuarkPlatformPkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptor.aslc               |   88 ++
 QuarkPlatformPkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptor.inf                |   45 +
 QuarkPlatformPkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptorPei.c               |   66 +
 QuarkPlatformPkg/Feature/Capsule/SystemBiosUpdateConfig/SystemBiosUpdateConfig.ini            |   62 +
 QuarkPlatformPkg/Library/PlatformBootManagerLib/PlatformBootManager.c                         |   95 +-
 QuarkPlatformPkg/Library/PlatformBootManagerLib/PlatformBootManager.h                         |    8 +-
 QuarkPlatformPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf                    |    8 +-
 QuarkPlatformPkg/Platform/Pei/PlatformInit/MemoryCallback.c                                   |    3 +-
 QuarkPlatformPkg/Quark.dsc                                                                    |   61 +-
 QuarkPlatformPkg/Quark.fdf                                                                    |   53 +
 QuarkPlatformPkg/QuarkCapsule.dsc                                                             |   44 +
 QuarkPlatformPkg/QuarkCapsule.fdf                                                             |   82 ++
 QuarkPlatformPkg/QuarkMin.dsc                                                                 |    7 +-
 SecurityPkg/Library/FmpAuthenticationPkcs7Lib/FmpAuthenticationPkcs7Lib.c                     |  144 ++
 SecurityPkg/Library/FmpAuthenticationPkcs7Lib/FmpAuthenticationPkcs7Lib.inf                   |   52 +
 SecurityPkg/Library/FmpAuthenticationPkcs7Lib/FmpAuthenticationPkcs7Lib.uni                   |   26 +
 SecurityPkg/Library/FmpAuthenticationRsa2048Sha256Lib/FmpAuthenticationRsa2048Sha256Lib.c     |  286 ++++
 SecurityPkg/Library/FmpAuthenticationRsa2048Sha256Lib/FmpAuthenticationRsa2048Sha256Lib.inf   |   53 +
 SecurityPkg/Library/FmpAuthenticationRsa2048Sha256Lib/FmpAuthenticationRsa2048Sha256Lib.uni   |   26 +
 SecurityPkg/SecurityPkg.dec                                                                   |    6 +
 SecurityPkg/SecurityPkg.dsc                                                                   |    3 +
 UefiCpuPkg/Application/MicrocodeCapsuleApp/AppSupport.c                                       |  480 ++++++
 UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.c                              |  283 ++++
 UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.inf                            |   62 +
 UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.uni                            |   22 +
 UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleAppExtra.uni                       |   19 +
 UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleDump.c                             |  171 +++
 UefiCpuPkg/Include/Guid/MicrocodeFmp.h                                                        |   21 +
 UefiCpuPkg/Include/Library/MicrocodeFlashAccessLib.h                                          |   39 +
 UefiCpuPkg/Library/MicrocodeFlashAccessLibNull/MicrocodeFlashAccessLibNull.c                  |   42 +
 UefiCpuPkg/Library/MicrocodeFlashAccessLibNull/MicrocodeFlashAccessLibNull.inf                |   40 +
 UefiCpuPkg/Library/MicrocodeFlashAccessLibNull/MicrocodeFlashAccessLibNull.uni                |   21 +
 UefiCpuPkg/MicrocodeUpdate/MicrocodeFmp.c                                                     |  641 ++++++++
 UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.c                                                  |  775 ++++++++++
 UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.h                                                  |  299 ++++
 UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.inf                                                |   68 +
 UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdateDxe.uni                                             |   21 +
 UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdateDxeExtra.uni                                        |   20 +
 UefiCpuPkg/UefiCpuPkg.dec                                                                     |    7 +
 UefiCpuPkg/UefiCpuPkg.dsc                                                                     |    3 +
 Vlv2TbltDevicePkg/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.c     |  192 +++
 Vlv2TbltDevicePkg/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.inf   |   47 +
 Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptor.aslc              |   86 ++
 Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptor.inf               |   45 +
 Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptorPei.c              |   66 +
 Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosUpdateConfig/SystemBiosUpdateConfig.ini           |   72 +
 Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosUpdateConfig/SystemBiosUpdateConfigGcc.ini        |   72 +
 Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLib.c                                     |  156 +-
 Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLib.inf                                   |    8 +-
 Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLibDxe.c                                  |   62 +
 Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLibDxe.inf                                |   49 +
 Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLibDxeRuntimeSmm.c                        |  188 +++
 Vlv2TbltDevicePkg/Library/FlashDeviceLib/SpiChipDefinitions.h                                 |    5 +-
 Vlv2TbltDevicePkg/Library/PlatformBdsLib/BdsPlatform.c                                        |  117 +-
 Vlv2TbltDevicePkg/Library/PlatformBdsLib/PlatformBdsLib.inf                                   |    2 +
 Vlv2TbltDevicePkg/PlatformCapsule.dsc                                                         |   44 +
 Vlv2TbltDevicePkg/PlatformCapsule.fdf                                                         |   81 ++
 Vlv2TbltDevicePkg/PlatformCapsuleGcc.fdf                                                      |   81 ++
 Vlv2TbltDevicePkg/PlatformPkg.fdf                                                             |  132 +-
 Vlv2TbltDevicePkg/PlatformPkgConfig.dsc                                                       |    3 +-
 Vlv2TbltDevicePkg/PlatformPkgGcc.fdf                                                          |  132 +-
 Vlv2TbltDevicePkg/PlatformPkgGccX64.dsc                                                       |   70 +-
 Vlv2TbltDevicePkg/PlatformPkgIA32.dsc                                                         |   70 +-
 Vlv2TbltDevicePkg/PlatformPkgX64.dsc                                                          |   70 +-
 Vlv2TbltDevicePkg/bld_vlv.bat                                                                 |    8 +-
 124 files changed, 17848 insertions(+), 384 deletions(-)
 create mode 100644 MdeModulePkg/Application/CapsuleApp/AppSupport.c
 create mode 100644 MdeModulePkg/Application/CapsuleApp/CapsuleApp.c
 create mode 100644 MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf
 create mode 100644 MdeModulePkg/Application/CapsuleApp/CapsuleApp.uni
 create mode 100644 MdeModulePkg/Application/CapsuleApp/CapsuleAppExtra.uni
 create mode 100644 MdeModulePkg/Application/CapsuleApp/CapsuleDump.c
 create mode 100644 MdeModulePkg/Include/Guid/EdkiiSystemFmpCapsule.h
 create mode 100644 MdeModulePkg/Include/Library/EdkiiSystemCapsuleLib.h
 create mode 100644 MdeModulePkg/Include/Library/FmpAuthenticationLib.h
 create mode 100644 MdeModulePkg/Include/Library/IniParsingLib.h
 create mode 100644 MdeModulePkg/Include/Library/PlatformFlashAccessLib.h
 create mode 100644 MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.c
 create mode 100644 MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.inf
 create mode 100644 MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.uni
 create mode 100644 MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleProcessLib.c
 create mode 100644 MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleReportLib.c
 create mode 100644 MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleRuntime.c
 create mode 100644 MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf
 create mode 100644 MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.uni
 create mode 100644 MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.c
 create mode 100644 MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.inf
 create mode 100644 MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.uni
 create mode 100644 MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.c
 create mode 100644 MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.inf
 create mode 100644 MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.uni
 create mode 100644 MdeModulePkg/Library/IniParsingLib/IniParsingLib.c
 create mode 100644 MdeModulePkg/Library/IniParsingLib/IniParsingLib.inf
 create mode 100644 MdeModulePkg/Library/IniParsingLib/IniParsingLib.uni
 create mode 100644 MdeModulePkg/Library/PlatformFlashAccessLibNull/PlatformFlashAccessLibNull.c
 create mode 100644 MdeModulePkg/Library/PlatformFlashAccessLibNull/PlatformFlashAccessLibNull.inf
 create mode 100644 MdeModulePkg/Library/PlatformFlashAccessLibNull/PlatformFlashAccessLibNull.uni
 create mode 100644 MdeModulePkg/Universal/RecoveryModuleLoadPei/ParseConfigProfile.c
 create mode 100644 MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPei.c
 create mode 100644 MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPei.h
 create mode 100644 MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPei.inf
 create mode 100644 MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPei.uni
 create mode 100644 MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPeiExtra.uni
 create mode 100644 MdeModulePkg/Universal/SystemBiosUpdate/ParseConfigProfile.c
 create mode 100644 MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosDxe.h
 create mode 100644 MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosMainDxe.c
 create mode 100644 MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosMainSetImage.c
 create mode 100644 MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosMainSetImageDummy.c
 create mode 100644 MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxe.inf
 create mode 100644 MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxe.uni
 create mode 100644 MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxeExtra.uni
 create mode 100644 MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxe.inf
 create mode 100644 MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxe.uni
 create mode 100644 MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxeExtra.uni
 create mode 100644 QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLibDxe.c
 create mode 100644 QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLibDxe.inf
 create mode 100644 QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/SpiFlashDevice.c
 create mode 100644 QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/SpiFlashDevice.h
 create mode 100644 QuarkPlatformPkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptor.aslc
 create mode 100644 QuarkPlatformPkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptor.inf
 create mode 100644 QuarkPlatformPkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptorPei.c
 create mode 100644 QuarkPlatformPkg/Feature/Capsule/SystemBiosUpdateConfig/SystemBiosUpdateConfig.ini
 create mode 100644 QuarkPlatformPkg/QuarkCapsule.dsc
 create mode 100644 QuarkPlatformPkg/QuarkCapsule.fdf
 create mode 100644 SecurityPkg/Library/FmpAuthenticationPkcs7Lib/FmpAuthenticationPkcs7Lib.c
 create mode 100644 SecurityPkg/Library/FmpAuthenticationPkcs7Lib/FmpAuthenticationPkcs7Lib.inf
 create mode 100644 SecurityPkg/Library/FmpAuthenticationPkcs7Lib/FmpAuthenticationPkcs7Lib.uni
 create mode 100644 SecurityPkg/Library/FmpAuthenticationRsa2048Sha256Lib/FmpAuthenticationRsa2048Sha256Lib.c
 create mode 100644 SecurityPkg/Library/FmpAuthenticationRsa2048Sha256Lib/FmpAuthenticationRsa2048Sha256Lib.inf
 create mode 100644 SecurityPkg/Library/FmpAuthenticationRsa2048Sha256Lib/FmpAuthenticationRsa2048Sha256Lib.uni
 create mode 100644 UefiCpuPkg/Application/MicrocodeCapsuleApp/AppSupport.c
 create mode 100644 UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.c
 create mode 100644 UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.inf
 create mode 100644 UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.uni
 create mode 100644 UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleAppExtra.uni
 create mode 100644 UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleDump.c
 create mode 100644 UefiCpuPkg/Include/Guid/MicrocodeFmp.h
 create mode 100644 UefiCpuPkg/Include/Library/MicrocodeFlashAccessLib.h
 create mode 100644 UefiCpuPkg/Library/MicrocodeFlashAccessLibNull/MicrocodeFlashAccessLibNull.c
 create mode 100644 UefiCpuPkg/Library/MicrocodeFlashAccessLibNull/MicrocodeFlashAccessLibNull.inf
 create mode 100644 UefiCpuPkg/Library/MicrocodeFlashAccessLibNull/MicrocodeFlashAccessLibNull.uni
 create mode 100644 UefiCpuPkg/MicrocodeUpdate/MicrocodeFmp.c
 create mode 100644 UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.c
 create mode 100644 UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.h
 create mode 100644 UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.inf
 create mode 100644 UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdateDxe.uni
 create mode 100644 UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdateDxeExtra.uni
 create mode 100644 Vlv2TbltDevicePkg/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.c
 create mode 100644 Vlv2TbltDevicePkg/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.inf
 create mode 100644 Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptor.aslc
 create mode 100644 Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptor.inf
 create mode 100644 Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptorPei.c
 create mode 100644 Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosUpdateConfig/SystemBiosUpdateConfig.ini
 create mode 100644 Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosUpdateConfig/SystemBiosUpdateConfigGcc.ini
 create mode 100644 Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLibDxe.c
 create mode 100644 Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLibDxe.inf
 create mode 100644 Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLibDxeRuntimeSmm.c
 create mode 100644 Vlv2TbltDevicePkg/PlatformCapsule.dsc
 create mode 100644 Vlv2TbltDevicePkg/PlatformCapsule.fdf
 create mode 100644 Vlv2TbltDevicePkg/PlatformCapsuleGcc.fdf

-- 
2.7.4.windows.1



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

* [PATCH 01/45] MdeModulePkg/Include: Add EDKII system FMP capsule header.
  2016-09-21  6:44 [PATCH 00/45] Add capsule update and recovery sample Jiewen Yao
@ 2016-09-21  6:44 ` Jiewen Yao
  2016-09-21  6:44 ` [PATCH 02/45] MdeModulePkg/Include: Add EdkiiSystemCapsuleLib definition Jiewen Yao
                   ` (47 subsequent siblings)
  48 siblings, 0 replies; 83+ messages in thread
From: Jiewen Yao @ 2016-09-21  6:44 UTC (permalink / raw)
  To: edk2-devel
  Cc: Feng Tian, Star Zeng, Michael D Kinney, Liming Gao, Chao Zhang,
	Jeff Fan

Add EDKII system FMP capsule header file.
This describes the EDKII system FMP capsule format.

Cc: Feng Tian <feng.tian@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Chao Zhang <chao.b.zhang@intel.com>
Cc: Jeff Fan <jeff.fan@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
---
 MdeModulePkg/Include/Guid/EdkiiSystemFmpCapsule.h | 110 ++++++++++++++++++++
 1 file changed, 110 insertions(+)

diff --git a/MdeModulePkg/Include/Guid/EdkiiSystemFmpCapsule.h b/MdeModulePkg/Include/Guid/EdkiiSystemFmpCapsule.h
new file mode 100644
index 0000000..9f609c1
--- /dev/null
+++ b/MdeModulePkg/Include/Guid/EdkiiSystemFmpCapsule.h
@@ -0,0 +1,110 @@
+/** @file
+  Guid & data structure used for Delivering Capsules Containing Updates to
+  EDKII System Firmware Management Protocol
+
+  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+
+#ifndef __EDKII_SYSTEM_FMP_CAPSULE_GUID_H__
+#define __EDKII_SYSTEM_FMP_CAPSULE_GUID_H__
+
+/**
+
+  Capsule Layout is below:
+  +------------------------------------------+
+  |    Capsule Header (OPTIONAL, WFU)        | <== ESRT.FwClass (Optional)
+  +------------------------------------------+
+  |          FMP Capsule Header              | <== EFI_FIRMWARE_MANAGEMENT_CAPSULE_ID_GUID
+  +------------------------------------------+
+  | FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER | <== PcdEdkiiSystemFmpCapsuleImageTypeIdGuid
+  +------------------------------------------+
+  |     EFI_FIRMWARE_IMAGE_AUTHENTICATION    |
+  +------------------------------------------+
+  |             FMP Payload                  |
+  +------------------------------------------+
+
+  System FMP Payload is below:
+  +------------------------------------------+
+  |            EFI_FIRMWARE_VOLUME           |
+  |  +------------------------------------+  |
+  |  |       FFS (Configure File)         |  | <== gEdkiiSystemFmpCapsuleConfigFileGuid
+  |  +------------------------------------+  |
+  |  |         FFS (Driver FV)            |  | <== gEdkiiSystemFmpCapsuleDriverFvFileGuid
+  |  +------------------------------------+  |
+  |  |         FFS (BIOS Image)           |  | <== PcdEdkiiSystemFirmwareFileGuid
+  |  |  +------------------------------+  |  |
+  |  |  |          FV Recovery         |  |  |
+  |  |  |------------------------------|  |  |
+  |  |  |           Fv Main            |  |  |
+  |  |  +------------------------------+  |  |
+  |  +------------------------------------+  |
+  +------------------------------------------+
+
+**/
+
+#define EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR_SIGNATURE  SIGNATURE_32('S', 'F', 'I', 'D')
+
+#pragma pack(1)
+typedef struct {
+  UINT32                                Signature;
+  UINT32                                HeaderLength; // Length of EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR, excluding NameString
+  UINT32                                Length;       // Length of the data structure, including NameString
+  // Below structure is similar as UEFI EFI_FIRMWARE_MANAGEMENT_PROTOCOL.GetPackageInfo()
+  UINT32                                PackageVersion;
+  UINT32                                PackageVersionNameStringOffset; // Offset from head, CHAR16 string including NULL terminate char
+  // Below structure is similar as UEFI EFI_FIRMWARE_IMAGE_DESCRIPTOR
+  UINT8                                 ImageIndex;
+  UINT8                                 Reserved[3];
+  EFI_GUID                              ImageTypeId;
+  UINT64                                ImageId;
+  UINT32                                ImageIdNameStringOffset; // Offset from head, CHAR16 string including NULL terminate char
+  UINT32                                Version;
+  UINT32                                VersionNameStringOffset; // Offset from head, CHAR16 string including NULL terminate char
+  UINT8                                 Reserved2[4];
+  UINT64                                Size;
+  UINT64                                AttributesSupported;
+  UINT64                                AttributesSetting;
+  UINT64                                Compatibilities;
+  UINT32                                LowestSupportedImageVersion;
+  UINT32                                LastAttemptVersion;
+  UINT32                                LastAttemptStatus;
+  UINT8                                 Reserved3[4];
+  UINT64                                HardwareInstance;
+  // real string data
+//CHAR16                                ImageIdNameStr[];        // CHAR16 string including NULL terminate char
+//CHAR16                                VersionNameStr[];        // CHAR16 string including NULL terminate char
+//CHAR16                                PackageVersionNameStr[]; // CHAR16 string including NULL terminate char
+} EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR;
+#pragma pack()
+
+/**
+  System Firmware Image Descriptor is below:
+            +----------------------+
+            |    BIOS (BIOS.FV)    |
+            |+--------------------+|
+            ||   FFS (Freeform)   || <== gEdkiiSystemFirmwareImageDescriptorFileGuid
+            ||+------------------+||
+            |||   SECTION (RAW)  |||
+            |||  System Firmware |||
+            ||| Image Descriptor |||
+            ||+------------------+||
+            |+--------------------+|
+            |                      |
+            |                      |
+            +----------------------+
+**/
+
+extern EFI_GUID gEdkiiSystemFirmwareImageDescriptorFileGuid;
+extern EFI_GUID gEdkiiSystemFmpCapsuleConfigFileGuid;
+extern EFI_GUID gEdkiiSystemFmpCapsuleDriverFvFileGuid;
+
+#endif
-- 
2.7.4.windows.1



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

* [PATCH 02/45] MdeModulePkg/Include: Add EdkiiSystemCapsuleLib definition.
  2016-09-21  6:44 [PATCH 00/45] Add capsule update and recovery sample Jiewen Yao
  2016-09-21  6:44 ` [PATCH 01/45] MdeModulePkg/Include: Add EDKII system FMP capsule header Jiewen Yao
@ 2016-09-21  6:44 ` Jiewen Yao
  2016-09-21  6:44 ` [PATCH 03/45] MdeModulePkg/Include: Add FmpAuthenticationLib header Jiewen Yao
                   ` (46 subsequent siblings)
  48 siblings, 0 replies; 83+ messages in thread
From: Jiewen Yao @ 2016-09-21  6:44 UTC (permalink / raw)
  To: edk2-devel; +Cc: Feng Tian, Star Zeng, Michael D Kinney, Liming Gao, Chao Zhang

This library is used to abstract the action for EDKII system FMP capsule,
such as extracting a component from capsule, or authenticate the capsule.

Cc: Feng Tian <feng.tian@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Chao Zhang <chao.b.zhang@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
---
 MdeModulePkg/Include/Library/EdkiiSystemCapsuleLib.h | 152 ++++++++++++++++++++
 1 file changed, 152 insertions(+)

diff --git a/MdeModulePkg/Include/Library/EdkiiSystemCapsuleLib.h b/MdeModulePkg/Include/Library/EdkiiSystemCapsuleLib.h
new file mode 100644
index 0000000..77d582b
--- /dev/null
+++ b/MdeModulePkg/Include/Library/EdkiiSystemCapsuleLib.h
@@ -0,0 +1,152 @@
+/** @file
+  EDKII System Capsule library.
+
+Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution.  The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+
+#ifndef __EDKII_SYSTEM_CAPSULE_LIB_H__
+#define __EDKII_SYSTEM_CAPSULE_LIB_H__
+
+#include <Guid/EdkiiSystemFmpCapsule.h>
+
+/**
+  Extract ImageFmpInfo from system firmware.
+
+  @param[in]  BiosImage               The BIOS image.
+  @param[in]  BiosImageSize           The size of the BIOS image in bytes.
+  @param[out] ImageFmpInfo            The ImageFmpInfo.
+  @param[out] ImageFmpInfoSize        The size of the ImageFmpInfo in bytes.
+
+  @retval TRUE  The ImageFmpInfo is extracted.
+  @retval FALSE The ImageFmpInfo is not extracted.
+**/
+BOOLEAN
+EFIAPI
+ExtractSystemFirmwareImageFmpInfo(
+  IN VOID                                      *BiosImage,
+  IN UINTN                                     BiosImageSize,
+  OUT EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR   **ImageFmpInfo,
+  OUT UINTN                                    *ImageFmpInfoSize
+  );
+
+/**
+  Extract the driver FV from an authenticated image.
+
+  @param[in]  AuthenticatedImage      The authenticated capsule image.
+  @param[in]  AuthenticatedImageSize  The size of the authenticated capsule image in bytes.
+  @param[out] DriverFvImage           The driver FV image.
+  @param[out] DriverFvImageSize       The size of the driver FV image in bytes.
+
+  @retval TRUE  The driver Fv is extracted.
+  @retval FALSE The driver Fv is not extracted.
+**/
+BOOLEAN
+EFIAPI
+ExtractDriverFvImage(
+  IN VOID                         *AuthenticatedImage,
+  IN UINTN                        AuthenticatedImageSize,
+  OUT VOID                        **DriverFvImage,
+  OUT UINTN                       *DriverFvImageSize
+  );
+
+/**
+  Extract the config image from an authenticated image.
+
+  @param[in]  AuthenticatedImage      The authenticated capsule image.
+  @param[in]  AuthenticatedImageSize  The size of the authenticated capsule image in bytes.
+  @param[out] ConfigImage             The config image.
+  @param[out] ConfigImageSize         The size of the config image in bytes.
+
+  @retval TRUE  The config image is extracted.
+  @retval FALSE The config image is not extracted.
+**/
+BOOLEAN
+EFIAPI
+ExtractConfigImage(
+  IN VOID                         *AuthenticatedImage,
+  IN UINTN                        AuthenticatedImageSize,
+  OUT VOID                        **ConfigImage,
+  OUT UINTN                       *ConfigImageSize
+  );
+
+/**
+  Extract the BIOS image from an authenticated image.
+
+  @param[in]  AuthenticatedImage      The authenticated capsule image.
+  @param[in]  AuthenticatedImageSize  The size of the authenticated capsule image in bytes.
+  @param[out] BiosImage               The BIOS image.
+  @param[out] BiosImageSize           The size of the BIOS image in bytes.
+
+  @retval TRUE  The BIOS image is extracted.
+  @retval FALSE The BIOS image is not extracted.
+**/
+BOOLEAN
+EFIAPI
+ExtractSystemFirmwareImage(
+  IN VOID                         *AuthenticatedImage,
+  IN UINTN                        AuthenticatedImageSize,
+  OUT VOID                        **BiosImage,
+  OUT UINTN                       *BiosImageSize
+  );
+
+/**
+  Extract the authenticated image from an FMP capsule image.
+
+  @param[in]  Image                   The FMP capsule image, including EFI_FIRMWARE_IMAGE_AUTHENTICATION.
+  @param[in]  ImageSize               The size of FMP capsule image in bytes.
+  @param[out] LastAttemptStatus       The last attempt status, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+  @param[out] AuthenticatedImage      The authenticated capsule image, excluding EFI_FIRMWARE_IMAGE_AUTHENTICATION.
+  @param[out] AuthenticatedImageSize  The size of the authenticated capsule image in bytes.
+
+  @retval TRUE  The authenticated image is extracted.
+  @retval FALSE The authenticated image is not extracted.
+**/
+BOOLEAN
+EFIAPI
+ExtractAuthenticatedImage(
+  IN VOID                         *Image,
+  IN UINTN                        ImageSize,
+  OUT UINT32                      *LastAttemptStatus,
+  OUT VOID                        **AuthenticatedImage,
+  OUT UINTN                       *AuthenticatedImageSize
+  );
+
+/**
+  Authenticated system firmware FMP capsule image.
+
+  @param[in]  Image                   The FMP capsule image, including EFI_FIRMWARE_IMAGE_AUTHENTICATION.
+  @param[in]  ImageSize               The size of FMP capsule image in bytes.
+  @param[in]  ForceVersionMatch       TRUE: The version of capsule must be as same as the version of current image.
+                                      FALSE: The version of capsule must be as same as greater than the lowest
+                                             supported version of current image.
+  @param[out] LastAttemptVersion      The last attempt version, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+  @param[out] LastAttemptStatus       The last attempt status, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+  @param[out] AuthenticatedImage      The authenticated capsule image, excluding EFI_FIRMWARE_IMAGE_AUTHENTICATION.
+  @param[out] AuthenticatedImageSize  The size of the authenticated capsule image in bytes.
+
+  @retval TRUE  Authentication passes and the authenticated image is extracted.
+  @retval FALSE Authentication fails and the authenticated image is not extracted.
+**/
+EFI_STATUS
+EFIAPI
+CapsuleAuthenticateSystemFirmware(
+  IN VOID                         *Image,
+  IN UINTN                        ImageSize,
+  IN BOOLEAN                      ForceVersionMatch,
+  OUT UINT32                      *LastAttemptVersion,
+  OUT UINT32                      *LastAttemptStatus,
+  OUT VOID                        **AuthenticatedImage,
+  OUT UINTN                       *AuthenticatedImageSize
+  );
+
+#endif
+
-- 
2.7.4.windows.1



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

* [PATCH 03/45] MdeModulePkg/Include: Add FmpAuthenticationLib header.
  2016-09-21  6:44 [PATCH 00/45] Add capsule update and recovery sample Jiewen Yao
  2016-09-21  6:44 ` [PATCH 01/45] MdeModulePkg/Include: Add EDKII system FMP capsule header Jiewen Yao
  2016-09-21  6:44 ` [PATCH 02/45] MdeModulePkg/Include: Add EdkiiSystemCapsuleLib definition Jiewen Yao
@ 2016-09-21  6:44 ` Jiewen Yao
  2016-09-21  6:44 ` [PATCH 04/45] MdeModulePkg/Include: Add IniParsingLib header Jiewen Yao
                   ` (45 subsequent siblings)
  48 siblings, 0 replies; 83+ messages in thread
From: Jiewen Yao @ 2016-09-21  6:44 UTC (permalink / raw)
  To: edk2-devel; +Cc: Feng Tian, Star Zeng, Michael D Kinney, Liming Gao, Chao Zhang

This library is used to authenticate a UEFI defined FMP Capsule.

Cc: Feng Tian <feng.tian@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Chao Zhang <chao.b.zhang@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
---
 MdeModulePkg/Include/Library/FmpAuthenticationLib.h | 91 ++++++++++++++++++++
 1 file changed, 91 insertions(+)

diff --git a/MdeModulePkg/Include/Library/FmpAuthenticationLib.h b/MdeModulePkg/Include/Library/FmpAuthenticationLib.h
new file mode 100644
index 0000000..895698e
--- /dev/null
+++ b/MdeModulePkg/Include/Library/FmpAuthenticationLib.h
@@ -0,0 +1,91 @@
+/** @file
+  FMP capsule authenitcation Library.
+
+Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution.  The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+
+#ifndef __FMP_AUTHENTICATION_LIB_H__
+#define __FMP_AUTHENTICATION_LIB_H__
+
+/**
+  The handler is used to do the authentication for FMP capsule based upon
+  EFI_FIRMWARE_IMAGE_AUTHENTICATION.
+
+  Caution: This function may receive untrusted input.
+
+  @param[in]    Image              Points to the new FMP authentication image,
+                                   start from EFI_FIRMWARE_IMAGE_AUTHENTICATION.
+  @param[in]    ImageSize          Size of the authentication image in bytes.
+  @param[out]   LastAttemptStatus  The last attempt status, which will be recorded
+                                   in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+
+  @retval RETURN_SUCCESS            Authentication pass.
+  @retval RETURN_SECURITY_VIOLATION Authentication fail.
+                                    The detail reson is recorded in LastAttemptStatus.
+**/
+typedef
+RETURN_STATUS
+(EFIAPI *FMP_AUTHENTICATION_HANDLER) (
+  IN VOID                         *Image,
+  IN UINTN                        ImageSize,
+  OUT UINT32                      *LastAttemptStatus
+  );
+
+/**
+  Register FMP authentication handler with CertType.
+
+  If CertType is NULL, then ASSERT().
+  If FmpAuthenticationHandler is NULL, then ASSERT().
+
+  @param[in]  CertType                   The certificate type associated with the FMP auth handler.
+  @param[in]  FmpAuthenticationHandler   The FMP authentication handler to be registered.
+
+  @retval  RETURN_SUCCESS           The handlers were registered.
+  @retval  RETURN_OUT_OF_RESOURCES  There are not enough resources available to register the handlers.
+**/
+RETURN_STATUS
+EFIAPI
+RegisterFmpAuthenticationHandler(
+  IN GUID                         *CertType,
+  IN FMP_AUTHENTICATION_HANDLER   FmpAuthenticationHandler
+  );
+
+/**
+  Execute FMP authentication handlers.
+
+  Caution: This function may receive untrusted input.
+
+  If Image is NULL, then ASSERT().
+  If ImageSize is 0, then ASSERT().
+  If LastAttemptStatus is NULL, then ASSERT().
+
+  @param[in]    Image              Points to the new FMP authentication image,
+                                   start from EFI_FIRMWARE_IMAGE_AUTHENTICATION.
+  @param[in]    ImageSize          Size of the authentication image in bytes.
+  @param[out]   LastAttemptStatus  The last attempt status, which will be recorded
+                                   in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+
+  @retval RETURN_SUCCESS            Authentication pass.
+  @retval RETURN_SECURITY_VIOLATION Authentication fail.
+                                    The detail reson is recorded in LastAttemptStatus.
+  @retval RETURN_UNSUPPORTED        No Authentication handler associated with CertType.
+**/
+RETURN_STATUS
+EFIAPI
+ExecuteFmpAuthenticationHandler(
+  IN  VOID                         *Image,
+  IN  UINTN                        ImageSize,
+  OUT UINT32                       *LastAttemptStatus
+  );
+
+#endif
+
-- 
2.7.4.windows.1



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

* [PATCH 04/45] MdeModulePkg/Include: Add IniParsingLib header.
  2016-09-21  6:44 [PATCH 00/45] Add capsule update and recovery sample Jiewen Yao
                   ` (2 preceding siblings ...)
  2016-09-21  6:44 ` [PATCH 03/45] MdeModulePkg/Include: Add FmpAuthenticationLib header Jiewen Yao
@ 2016-09-21  6:44 ` Jiewen Yao
  2016-09-29  6:53   ` Ni, Ruiyu
  2016-09-21  6:44 ` [PATCH 05/45] MdeModulePkg/Include: Add PlatformFlashAccessLib header Jiewen Yao
                   ` (44 subsequent siblings)
  48 siblings, 1 reply; 83+ messages in thread
From: Jiewen Yao @ 2016-09-21  6:44 UTC (permalink / raw)
  To: edk2-devel; +Cc: Feng Tian, Star Zeng, Michael D Kinney, Liming Gao, Chao Zhang

This library is used to parse the INI configuration file.
The INI configuration file is used in EDKII capsule image to describe
the capsule information.

The INI file format is:
================
[SectionName]
EntryName=EntryValue
================

Cc: Feng Tian <feng.tian@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Chao Zhang <chao.b.zhang@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
---
 MdeModulePkg/Include/Library/IniParsingLib.h | 153 ++++++++++++++++++++
 1 file changed, 153 insertions(+)

diff --git a/MdeModulePkg/Include/Library/IniParsingLib.h b/MdeModulePkg/Include/Library/IniParsingLib.h
new file mode 100644
index 0000000..e3ed18d
--- /dev/null
+++ b/MdeModulePkg/Include/Library/IniParsingLib.h
@@ -0,0 +1,153 @@
+/** @file
+  INI configuration parsing library.
+
+  The INI file format is:
+    ================
+    [SectionName]
+    EntryName=EntryValue
+    ================
+
+Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution.  The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+
+#ifndef __INI_PARSING_LIB_H__
+#define __INI_PARSING_LIB_H__
+
+/**
+  Open an INI config file and return a context.
+
+  @param DataBuffer      Config raw file buffer.
+  @param BufferSize      Size of raw buffer.
+
+  @retval EFI_SUCCESS           Config data buffer is opened and context is returned.
+  @retval EFI_OUT_OF_RESOURCES  No enough memory is allocated.
+**/
+VOID *
+EFIAPI
+OpenDataFile(
+  IN      UINT8                         *DataBuffer,
+  IN      UINTN                         BufferSize
+  );
+
+/**
+  Get section entry string value.
+
+  @param Context         INI Config file context.
+  @param SectionName     Section name.
+  @param EntryName       Section entry name.
+  @param EntryValue      Point to the got entry string value.
+
+  @retval EFI_SUCCESS    Section entry string value is got.
+  @retval EFI_NOT_FOUND  Section is not found.
+**/
+EFI_STATUS
+EFIAPI
+GetStringFromDataFile(
+  IN      VOID                          *Context,
+  IN      CHAR8                         *SectionName,
+  IN      CHAR8                         *EntryName,
+  OUT     CHAR8                         **EntryValue
+  );
+
+/**
+  Get section entry GUID value.
+
+  @param Context         INI Config file context.
+  @param SectionName     Section name.
+  @param EntryName       Section entry name.
+  @param Guid            Point to the got GUID value.
+
+  @retval EFI_SUCCESS    Section entry GUID value is got.
+  @retval EFI_NOT_FOUND  Section is not found.
+**/
+EFI_STATUS
+EFIAPI
+GetGuidFromDataFile(
+  IN      VOID                          *Context,
+  IN      CHAR8                         *SectionName,
+  IN      CHAR8                         *EntryName,
+  OUT     EFI_GUID                      *Guid
+  );
+
+/**
+  Get section entry UINTN value.
+
+  @param Context         INI Config file context.
+  @param SectionName     Section name.
+  @param EntryName       Section entry name.
+  @param Data            Point to the got UINTN value.
+
+  @retval EFI_SUCCESS    Section entry UINTN value is got.
+  @retval EFI_NOT_FOUND  Section is not found.
+**/
+EFI_STATUS
+EFIAPI
+GetDecimalUintnFromDataFile(
+  IN      VOID                          *Context,
+  IN      CHAR8                         *SectionName,
+  IN      CHAR8                         *EntryName,
+  OUT     UINTN                         *Data
+  );
+
+/**
+  Get section entry heximal UINTN value.
+
+  @param Context         INI Config file context.
+  @param SectionName     Section name.
+  @param EntryName       Section entry name.
+  @param Data            Point to the got heximal UINTN value.
+
+  @retval EFI_SUCCESS    Section entry heximal UINTN value is got.
+  @retval EFI_NOT_FOUND  Section is not found.
+**/
+EFI_STATUS
+EFIAPI
+GetHexUintnFromDataFile(
+  IN      VOID                          *Context,
+  IN      CHAR8                         *SectionName,
+  IN      CHAR8                         *EntryName,
+  OUT     UINTN                         *Data
+  );
+
+/**
+  Get section entry heximal UINT64 value.
+
+  @param Context         INI Config file context.
+  @param SectionName     Section name.
+  @param EntryName       Section entry name.
+  @param Data            Point to the got heximal UINT64 value.
+
+  @retval EFI_SUCCESS    Section entry heximal UINT64 value is got.
+  @retval EFI_NOT_FOUND  Section is not found.
+**/
+EFI_STATUS
+EFIAPI
+GetHexUint64FromDataFile(
+  IN      VOID                          *Context,
+  IN      CHAR8                         *SectionName,
+  IN      CHAR8                         *EntryName,
+  OUT     UINT64                        *Data
+  );
+
+/**
+  Close an INI config file and free the context.
+
+  @param Context         INI Config file context.
+**/
+VOID
+EFIAPI
+CloseDataFile(
+  IN      VOID                          *Context
+  );
+
+#endif
+
-- 
2.7.4.windows.1



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

* [PATCH 05/45] MdeModulePkg/Include: Add PlatformFlashAccessLib header.
  2016-09-21  6:44 [PATCH 00/45] Add capsule update and recovery sample Jiewen Yao
                   ` (3 preceding siblings ...)
  2016-09-21  6:44 ` [PATCH 04/45] MdeModulePkg/Include: Add IniParsingLib header Jiewen Yao
@ 2016-09-21  6:44 ` Jiewen Yao
  2016-09-21  6:44 ` [PATCH 06/45] MdeModulePkg/CapsuleLib: Add ProcessCapsules() API Jiewen Yao
                   ` (43 subsequent siblings)
  48 siblings, 0 replies; 83+ messages in thread
From: Jiewen Yao @ 2016-09-21  6:44 UTC (permalink / raw)
  To: edk2-devel; +Cc: Feng Tian, Star Zeng, Michael D Kinney, Liming Gao, Chao Zhang

This library is used to abstract platform flash access.
This library is consumed by a capsule update module.
It may cover BIOS region and/or non-BIOS region.

Cc: Feng Tian <feng.tian@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Chao Zhang <chao.b.zhang@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
---
 MdeModulePkg/Include/Library/PlatformFlashAccessLib.h | 59 ++++++++++++++++++++
 1 file changed, 59 insertions(+)

diff --git a/MdeModulePkg/Include/Library/PlatformFlashAccessLib.h b/MdeModulePkg/Include/Library/PlatformFlashAccessLib.h
new file mode 100644
index 0000000..694c1c5
--- /dev/null
+++ b/MdeModulePkg/Include/Library/PlatformFlashAccessLib.h
@@ -0,0 +1,59 @@
+/** @file
+  Platform flash device access library.
+
+  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+
+#ifndef __PLATFORM_FLASH_ACCESS_LIB_H__
+#define __PLATFORM_FLASH_ACCESS_LIB_H__
+
+typedef enum {
+  FlashAddressTypeRelativeAddress,
+  FlashAddressTypeAbsoluteAddress,
+  FlashAddressTypeMax,
+} FLASH_ADDRESS_TYPE;
+
+//
+// Type 0 ~ 0x7FFFFFFF is defined in this library.
+// Type 0x80000000 ~ 0xFFFFFFFF is reserved for OEM.
+//
+typedef enum {
+  PlatformFirmwareTypeBios,
+  PlatformFirmwareTypeNvRam,
+  PlatformFirmwareTypeMax,
+} PLATFORM_FIRMWARE_TYPE;
+
+/**
+  Perform flash write opreation.
+
+  @param FirmwareType      The type of firmware.
+  @param FlashAddress      The address of flash device to be accessed.
+  @param FlashAddressType  The type of flash device address.
+  @param Buffer            The pointer to the data buffer.
+  @param Length            The length of data buffer in bytes.
+
+  @retval EFI_SUCCESS           The operation returns successfully.
+  @retval EFI_WRITE_PROTECTED   The flash device is read only.
+  @retval EFI_UNSUPPORTED       The flash device access is unsupported.
+  @retval EFI_INVALID_PARAMETER The input parameter is not valid.
+**/
+EFI_STATUS
+EFIAPI
+PerformFlashWrite (
+  IN PLATFORM_FIRMWARE_TYPE       FirmwareType,
+  IN EFI_PHYSICAL_ADDRESS         FlashAddress,
+  IN FLASH_ADDRESS_TYPE           FlashAddressType,
+  IN VOID                         *Buffer,
+  IN UINTN                        Length
+  );
+
+#endif
-- 
2.7.4.windows.1



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

* [PATCH 06/45] MdeModulePkg/CapsuleLib: Add ProcessCapsules() API.
  2016-09-21  6:44 [PATCH 00/45] Add capsule update and recovery sample Jiewen Yao
                   ` (4 preceding siblings ...)
  2016-09-21  6:44 ` [PATCH 05/45] MdeModulePkg/Include: Add PlatformFlashAccessLib header Jiewen Yao
@ 2016-09-21  6:44 ` Jiewen Yao
  2016-09-21  6:44 ` [PATCH 07/45] MdeModulePkg/MdeModulePkg.dec: Add capsule related definition Jiewen Yao
                   ` (42 subsequent siblings)
  48 siblings, 0 replies; 83+ messages in thread
From: Jiewen Yao @ 2016-09-21  6:44 UTC (permalink / raw)
  To: edk2-devel; +Cc: Feng Tian, Star Zeng, Michael D Kinney, Liming Gao, Chao Zhang

ProcessCapsules() API can be used by platform BDS to process all capsules.

Cc: Feng Tian <feng.tian@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Chao Zhang <chao.b.zhang@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
---
 MdeModulePkg/Include/Library/CapsuleLib.h | 45 ++++++++++++++++++--
 1 file changed, 42 insertions(+), 3 deletions(-)

diff --git a/MdeModulePkg/Include/Library/CapsuleLib.h b/MdeModulePkg/Include/Library/CapsuleLib.h
index 487cb0f..659c077 100644
--- a/MdeModulePkg/Include/Library/CapsuleLib.h
+++ b/MdeModulePkg/Include/Library/CapsuleLib.h
@@ -2,7 +2,7 @@
 
   This library class defines a set of interfaces for how to process capsule image updates.
 
-Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2007 - 2016, Intel Corporation. All rights reserved.<BR>
 This program and the accompanying materials are licensed and made available under 
 the terms and conditions of the BSD License that accompanies this distribution.  
 The full text of the license may be found at
@@ -20,7 +20,9 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
   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.
-  
+
+  Caution: This function may receive untrusted input.
+
   @param  CapsuleHeader    Pointer to the UEFI capsule image to be checked.
   
   @retval EFI_SUCESS       Input capsule is supported by firmware.
@@ -35,7 +37,9 @@ SupportCapsuleImage (
 /**
   The firmware-specific implementation processes the capsule image
   if it recognized the format of this capsule image.
-  
+
+  Caution: This function may receive untrusted input.
+
   @param  CapsuleHeader    Pointer to the UEFI capsule image to be processed. 
    
   @retval EFI_SUCESS       Capsule Image processed successfully. 
@@ -47,4 +51,39 @@ ProcessCapsuleImage (
   IN EFI_CAPSULE_HEADER *CapsuleHeader
   );
 
+/**
+
+  This routine is called to process capsules.
+
+  Caution: This function may receive untrusted input.
+
+  If the current boot mode is NOT BOOT_ON_FLASH_UPDATE, this routine does nothing.
+  If the current boot mode is BOOT_ON_FLASH_UPDATE, the capsules reported in
+  EFI_HOB_UEFI_CAPSULE are processed. If there is no EFI_HOB_UEFI_CAPSULE, this
+  routine does nothing.
+
+  This routine should be called twice in BDS.
+  1) The first call must be before EndOfDxe. The system capsules is processed.
+     If device capsule FMP protocols are exposted at this time, the device
+     capsules are processed.
+     Each individual capsule result is recorded in capsule record variable.
+     System may reset in this function, if reset is required by capsule.
+
+  2) The second call must be after EndOfDxe and after ConnectAll, so that all
+     device capsule FMP protocols are exposed.
+     The system capsules are skipped. If the device capsules are NOT processed
+     in first call, they are processed here.
+     Each individual capsule result is recorded in capsule record variable.
+     System may reset in this function, if reset is required by capsule.
+
+  @retval EFI_SUCCESS             There is no error when processing capsules.
+  @retval EFI_OUT_OF_RESOURCES    No enough resource to process capsules.
+
+**/
+EFI_STATUS
+EFIAPI
+ProcessCapsules(
+  VOID
+  );
+
 #endif
-- 
2.7.4.windows.1



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

* [PATCH 07/45] MdeModulePkg/MdeModulePkg.dec: Add capsule related definition.
  2016-09-21  6:44 [PATCH 00/45] Add capsule update and recovery sample Jiewen Yao
                   ` (5 preceding siblings ...)
  2016-09-21  6:44 ` [PATCH 06/45] MdeModulePkg/CapsuleLib: Add ProcessCapsules() API Jiewen Yao
@ 2016-09-21  6:44 ` Jiewen Yao
  2016-09-21  6:44 ` [PATCH 08/45] MdeModulePkg/IniParsingLib: Add InitParsingLib instance Jiewen Yao
                   ` (41 subsequent siblings)
  48 siblings, 0 replies; 83+ messages in thread
From: Jiewen Yao @ 2016-09-21  6:44 UTC (permalink / raw)
  To: edk2-devel; +Cc: Feng Tian, Star Zeng, Michael D Kinney, Liming Gao, Chao Zhang

1) Add capsule related GUID.
   EdkiiSystemFmpCapsule
2) Add capsule related library.
   EdkiiSystemCapsuleLib
   FmpAuthenticationLib
   IniParsingLib
   PlatformFlashAccessLib.c
3) Add capsule related status code PCD.
   PcdStatusCodeSubClassCapsule
   PcdCapsuleStatusCodeProcessCapsulesBegin
   PcdCapsuleStatusCodeProcessCapsulesEnd
   PcdCapsuleStatusCodeUpdatingFirmware
   PcdCapsuleStatusCodeUpdateFirmwareSuccess
   PcdCapsuleStatusCodeUpdateFirmwareFailed
   PcdCapsuleStatusCodeResettingSystem
4) Add capsule status variable PCD - CapsuleMax value.
   PcdCapsuleMax
5) Add EDKII system capsule related DynamicEx PCD
   PcdEdkiiSystemFmpCapsuleMonotonicCount
   PcdEdkiiSystemFirmwareImageDescriptor
   PcdEdkiiSystemFirmwareFileGuid
   PcdEdkiiSystemFmpCapsuleImageTypeIdGuid
   NOTE: We use DynamicEx here because the update driver may be in
   the capsule FMP, instead of system BIOS.
   The update driver MUST use the PCD info produced system BIOS.

Cc: Feng Tian <feng.tian@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Chao Zhang <chao.b.zhang@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
---
 MdeModulePkg/MdeModulePkg.dec | 106 ++++++++++++++++++++
 1 file changed, 106 insertions(+)

diff --git a/MdeModulePkg/MdeModulePkg.dec b/MdeModulePkg/MdeModulePkg.dec
index 8d90f16..113abf7 100644
--- a/MdeModulePkg/MdeModulePkg.dec
+++ b/MdeModulePkg/MdeModulePkg.dec
@@ -157,6 +157,22 @@
   #
   MemoryProfileLib|Include/Library/MemoryProfileLib.h
 
+  ## @libraryclass  Provides services to authenticate a UEFI defined FMP Capsule.
+  #
+  FmpAuthenticationLib|Include/Library/FmpAuthenticationLib.h
+
+  ## @libraryclass  Provides services for EDKII system FMP capsule.
+  #
+  EdkiiSystemCapsuleLib|Include/Library/EdkiiSystemCapsuleLib.h
+
+  ## @libraryclass  Provides services to parse the INI configuration file.
+  #
+  IniParsingLib|Include/Library/IniParsingLib.h
+
+  ## @libraryclass  Provides services to access flash device.
+  #
+  PlatformFlashAccessLib|Include/Library/PlatformFlashAccessLib.h
+
 [Guids]
   ## MdeModule package token space guid
   # Include/Guid/MdeModulePkgTokenSpace.h
@@ -355,6 +371,11 @@
   ## Include/Guid/PiSmmCommunicationRegionTable.h
   gEdkiiPiSmmCommunicationRegionTableGuid = { 0x4e28ca50, 0xd582, 0x44ac, {0xa1, 0x1f, 0xe3, 0xd5, 0x65, 0x26, 0xdb, 0x34}}
 
+  ## Include/Guid/EdkiiSystemFmpCapsule.h
+  gEdkiiSystemFirmwareImageDescriptorFileGuid = {0x90b2b846, 0xca6d, 0x4d6e, {0xa8, 0xd3, 0xc1, 0x40, 0xa8, 0xe1, 0x10, 0xac}}
+  gEdkiiSystemFmpCapsuleConfigFileGuid        = {0x812136d3, 0x4d3a, 0x433a, {0x94, 0x18, 0x29, 0xbb, 0x9b, 0xf7, 0x8f, 0x6e}}
+  gEdkiiSystemFmpCapsuleDriverFvFileGuid      = {0xce57b167, 0xb0e4, 0x41e8, {0xa8, 0x97, 0x5f, 0x4f, 0xeb, 0x78, 0x1d, 0x40}}
+
 [Ppis]
   ## Include/Ppi/AtaController.h
   gPeiAtaControllerPpiGuid       = { 0xa45e60d1, 0xc719, 0x44aa, { 0xb0, 0x7a, 0xaa, 0x77, 0x7f, 0x85, 0x90, 0x6d }}
@@ -1130,6 +1151,52 @@
   # @Prompt MAX repair count
   gEfiMdeModulePkgTokenSpaceGuid.PcdMaxRepairCount|0x00|UINT32|0x00010076
 
+  ## Status Code for Capsule subclass definitions.<BR><BR>
+  #  EFI_SOFTWARE_CAPSULE  = (EFI_SOFTWARE | 0x00150000) = 0x03150000<BR>
+  # @Prompt Status Code for Capsule subclass definitions
+  # @ValidList  0x80000003 | 0x03150000
+  gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeSubClassCapsule|0x03150000|UINT32|0x00000100
+
+  ## Status Code for Capsule definitions.<BR><BR>
+  #  EFI_CAPSULE_PROCESS_CAPSULES_BEGIN  = (EFI_SUBCLASS_SPECIFIC | 0x00000001) = 0x00010001<BR>
+  # @Prompt Status Code for Capsule definitions
+  # @ValidList  0x80000003 | 0x00010001
+  gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleStatusCodeProcessCapsulesBegin|0x00010001|UINT32|0x00000101
+
+  ## Status Code for Capsule definitions.<BR><BR>
+  #  EFI_CAPSULE_PROCESS_CAPSULES_END    = (EFI_SUBCLASS_SPECIFIC | 0x00000002) = 0x00010002<BR>
+  # @Prompt Status Code for Capsule definitions
+  # @ValidList  0x80000003 | 0x00010002
+  gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleStatusCodeProcessCapsulesEnd|0x00010002|UINT32|0x00000102
+
+  ## Status Code for Capsule definitions.<BR><BR>
+  #  EFI_CAPSULE_UPDATING_FIRMWARE       = (EFI_SUBCLASS_SPECIFIC | 0x00000003) = 0x00010003<BR>
+  # @Prompt Status Code for Capsule definitions
+  # @ValidList  0x80000003 | 0x00010003
+  gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleStatusCodeUpdatingFirmware|0x00010003|UINT32|0x00000103
+
+  ## Status Code for Capsule definitions.<BR><BR>
+  #  EFI_CAPSULE_UPDATE_FIRMWARE_SUCCESS = (EFI_SUBCLASS_SPECIFIC | 0x00000004) = 0x00010004<BR>
+  # @Prompt Status Code for Capsule definitions
+  # @ValidList  0x80000003 | 0x00010004
+  gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleStatusCodeUpdateFirmwareSuccess|0x00010004|UINT32|0x00000104
+
+  ## Status Code for Capsule definitions.<BR><BR>
+  #  EFI_CAPSULE_UPDATE_FIRMWARE_FAILED  = (EFI_SUBCLASS_SPECIFIC | 0x00000005) = 0x00010005<BR>
+  # @Prompt Status Code for Capsule definitions
+  # @ValidList  0x80000003 | 0x00010005
+  gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleStatusCodeUpdateFirmwareFailed|0x00010005|UINT32|0x00000105
+
+  ## Status Code for Capsule definitions.<BR><BR>
+  #  EFI_CAPSULE_RESETTING_SYSTEM        = (EFI_SUBCLASS_SPECIFIC | 0x00000006) = 0x00010006<BR>
+  # @Prompt Status Code for Capsule definitions
+  # @ValidList  0x80000003 | 0x00010001
+  gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleStatusCodeResettingSystem|0x00010006|UINT32|0x00000106
+
+  ## CapsuleMax value in capsule report variable.
+  # @Prompt CapsuleMax value in capsule report variable.
+  gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleMax|0xFFFF|UINT16|0x00000107
+
 [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.
@@ -1621,5 +1688,44 @@
   # @ValidList  0x80000001 | 0x0
   gEfiMdeModulePkgTokenSpaceGuid.PcdIdentifyMappingPageTablePtr|0x0|UINT64|0x00030002
 
+[PcdsDynamicEx]
+  ## This dynamic PCD hold the FMP capsule monotonic count value for current
+  #  BIOS. It is used to ensure freshness/no replay on firmware update.
+  #  Only if the new system FmpCapsule EFI_FIRMWARE_IMAGE_AUTHENTICATION.MonotonicCount
+  #  is no less than this PcdFmpCapsuleMonotonicCount, the EDKII system
+  #  FmpCapsule will be processed.
+  #  It must be dynamicEx, because the EDKII system firmware update module may
+  #  consume the PCD produced in current BIOS.
+  # @Prompt EDKII system FMP capsule monotonic count.
+  gEfiMdeModulePkgTokenSpaceGuid.PcdEdkiiSystemFmpCapsuleMonotonicCount|1|UINT64|0x000035
+
+  ## This dynamic PCD hold the EDKII system firmware image descriptor.
+  #  This information can be used for version check in EDKII system FMP capsule.
+  #  Only if the new EdkiiSystemFrimwareImageDescriptor.Version is no less than
+  #  the current PcdEdkiiSystemFirmwareImageDescriptor.LowestSupportedVersion,
+  #  the EDKII system FmpCapsule will be processed.
+  #  It must be dynamicEx, because the EDKII system firmware update module may
+  #  consume the PCD produced in current BIOS.
+  # @Prompt EDKII system firwmare image descriptor.
+  gEfiMdeModulePkgTokenSpaceGuid.PcdEdkiiSystemFirmwareImageDescriptor|{0}|VOID*|0x00000037
+
+  ## This dynamic PCD hold the GUID of a firmware FFS which includes EDKII
+  #  system firmware image.
+  #  An EDKII system firmware udpate module need consume this PCD to extract
+  #  the EDKII system firmware from the capsule image.
+  #  It must be dynamicEx, because the EDKII system firmware update module may
+  #  consume the PCD produced in current BIOS.
+  # @Prompt EDKII system firmware image FFS GUID.
+  gEfiMdeModulePkgTokenSpaceGuid.PcdEdkiiSystemFirmwareFileGuid|{0xb2, 0x9e, 0x9c, 0xaf, 0xad, 0x12, 0x3e, 0x4d, 0xa4, 0xd4, 0x96, 0xf6, 0xc9, 0x96, 0x62, 0x15}|VOID*|0x00001010
+
+  ## This dynamic PCD hold a list GUIDs for the ImageTypeId to indicate the
+  #  FMP capsule is EDKII system FMP.
+  #  An EDKII system firmware udpate module need consume this PCD to know if
+  #  This FMP capsule is a system FMP or device FMP.
+  #  It must be dynamicEx, because the EDKII system firmware update module may
+  #  consume the PCD produced in current BIOS.
+  # @Prompt A list of EDKII system FMP ImageTypeId GUIDs
+  gEfiMdeModulePkgTokenSpaceGuid.PcdEdkiiSystemFmpCapsuleImageTypeIdGuid|{0xd3, 0xee, 0x7e, 0x3f, 0x91, 0xf4, 0x1e, 0x40, 0x9e, 0xce, 0x74, 0x31, 0x32, 0x2e, 0xad, 0xf6}|VOID*|0x00001011
+
 [UserExtensions.TianoCore."ExtraFiles"]
   MdeModulePkgExtra.uni
-- 
2.7.4.windows.1



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

* [PATCH 08/45] MdeModulePkg/IniParsingLib: Add InitParsingLib instance.
  2016-09-21  6:44 [PATCH 00/45] Add capsule update and recovery sample Jiewen Yao
                   ` (6 preceding siblings ...)
  2016-09-21  6:44 ` [PATCH 07/45] MdeModulePkg/MdeModulePkg.dec: Add capsule related definition Jiewen Yao
@ 2016-09-21  6:44 ` Jiewen Yao
  2016-09-21  6:44 ` [PATCH 09/45] MdeModulePkg/FmpAuthenticationLib: Add FmpAuthenticationLib instance Jiewen Yao
                   ` (40 subsequent siblings)
  48 siblings, 0 replies; 83+ messages in thread
From: Jiewen Yao @ 2016-09-21  6:44 UTC (permalink / raw)
  To: edk2-devel; +Cc: Feng Tian, Star Zeng, Michael D Kinney, Liming Gao, Chao Zhang

This library is used to parse the INI configuration file.
The INI configuration file is used in EDKII capsule image to describe
the capsule information.

Cc: Feng Tian <feng.tian@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Chao Zhang <chao.b.zhang@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
---
 MdeModulePkg/Library/IniParsingLib/IniParsingLib.c   | 1053 ++++++++++++++++++++
 MdeModulePkg/Library/IniParsingLib/IniParsingLib.inf |   42 +
 MdeModulePkg/Library/IniParsingLib/IniParsingLib.uni |   22 +
 3 files changed, 1117 insertions(+)

diff --git a/MdeModulePkg/Library/IniParsingLib/IniParsingLib.c b/MdeModulePkg/Library/IniParsingLib/IniParsingLib.c
new file mode 100644
index 0000000..e5dd813
--- /dev/null
+++ b/MdeModulePkg/Library/IniParsingLib/IniParsingLib.c
@@ -0,0 +1,1053 @@
+/** @file
+  This library parses the INI configuration file.
+
+  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions
+  of the BSD License which accompanies this distribution.  The
+  full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Uefi.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+
+#define IS_HYPHEN(a)               ((a) == '-')
+#define IS_NULL(a)                 ((a) == '\0')
+
+#define MAX_LINE_LENGTH           512
+
+typedef struct _SECTION_ITEM SECTION_ITEM;
+struct _SECTION_ITEM {
+  CHAR8                           *ptrSection;
+  UINTN                           SecNameLen;
+  CHAR8                           *ptrEntry;
+  CHAR8                           *ptrValue;
+  SECTION_ITEM                    *ptrNext;
+};
+
+typedef struct _COMMENT_LINE COMMENT_LINE;
+struct _COMMENT_LINE {
+  CHAR8                           *ptrComment;
+  COMMENT_LINE                    *ptrNext;
+};
+
+typedef struct {
+  SECTION_ITEM                  *SectionHead;
+  COMMENT_LINE                  *CommentHead;
+} INI_PARSING_LIB_CONTEXT;
+
+/**
+  Copy one line data from buffer data to the line buffer.
+
+  @param Buffer          Buffer data.
+  @param BufferSize      Buffer Size.
+  @param LineBuffer      Line buffer to store the found line data.
+  @param LineSize        On input, size of the input line buffer.
+                         On output, size of the actual line buffer.
+
+  @retval EFI_BUFFER_TOO_SMALL  The size of input line buffer is not enough.
+  @retval EFI_SUCCESS           Copy line data into the line buffer.
+
+**/
+EFI_STATUS
+ProfileGetLine (
+  IN      UINT8                         *Buffer,
+  IN      UINTN                         BufferSize,
+  IN OUT  UINT8                         *LineBuffer,
+  IN OUT  UINTN                         *LineSize
+  )
+{
+  UINTN                                 Length;
+  UINT8                                 *PtrBuf;
+  UINTN                                 PtrEnd;
+
+  PtrBuf      = Buffer;
+  PtrEnd      = (UINTN)Buffer + BufferSize;
+
+  //
+  // 0x0D indicates a line break. Otherwise there is no line break
+  //
+  while ((UINTN)PtrBuf < PtrEnd) {
+    if (*PtrBuf == 0x0D) {
+      break;
+    }
+    PtrBuf++;
+  }
+
+  if ((UINTN)PtrBuf >= (PtrEnd - 1)) {
+    //
+    // The buffer ends without any line break
+    // or it is the last character of the buffer
+    //
+    Length    = BufferSize;
+  } else if (*(PtrBuf + 1) == 0x0A) {
+    //
+    // Further check if a 0x0A follows. If yes, count 0xA
+    //
+    Length    = (UINTN) PtrBuf - (UINTN) Buffer + 2;
+  } else {
+    Length    = (UINTN) PtrBuf - (UINTN) Buffer + 1;
+  }
+
+  if (Length > (*LineSize)) {
+    *LineSize = Length;
+    return EFI_BUFFER_TOO_SMALL;
+  }
+
+  SetMem (LineBuffer, *LineSize, 0x0);
+  *LineSize   = Length;
+  CopyMem (LineBuffer, Buffer, Length);
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Trim Buffer by removing all CR, LF, TAB, and SPACE chars in its head and tail.
+
+  @param Buffer          On input,  buffer data to be trimed.
+                         On output, the trimmed buffer.
+  @param BufferSize      On input,  size of original buffer data.
+                         On output, size of the trimmed buffer.
+
+**/
+VOID
+ProfileTrim (
+  IN OUT  UINT8                         *Buffer,
+  IN OUT  UINTN                         *BufferSize
+  )
+{
+  UINTN                                 Length;
+  UINT8                                 *PtrBuf;
+  UINT8                                 *PtrEnd;
+
+  if (*BufferSize == 0) {
+    return;
+  }
+
+  //
+  // Trim the tail first, include CR, LF, TAB, and SPACE.
+  //
+  Length          = *BufferSize;
+  PtrBuf          = (UINT8 *) ((UINTN) Buffer + Length - 1);
+  while (PtrBuf >= Buffer) {
+    if ((*PtrBuf != 0x0D) && (*PtrBuf != 0x0A )
+      && (*PtrBuf != 0x20) && (*PtrBuf != 0x09)) {
+      break;
+    }
+    PtrBuf --;
+  }
+
+  //
+  // all spaces, a blank line, return directly;
+  //
+  if (PtrBuf < Buffer) {
+    *BufferSize   = 0;
+    return;
+  }
+
+  Length          = (UINTN)PtrBuf - (UINTN)Buffer + 1;
+  PtrEnd          = PtrBuf;
+  PtrBuf          = Buffer;
+
+  //
+  // Now skip the heading CR, LF, TAB and SPACE
+  //
+  while (PtrBuf <= PtrEnd) {
+    if ((*PtrBuf != 0x0D) && (*PtrBuf != 0x0A )
+      && (*PtrBuf != 0x20) && (*PtrBuf != 0x09)) {
+      break;
+    }
+    PtrBuf++;
+  }
+
+  //
+  // If no heading CR, LF, TAB or SPACE, directly return
+  //
+  if (PtrBuf == Buffer) {
+    *BufferSize   = Length;
+    return;
+  }
+
+  *BufferSize     = (UINTN)PtrEnd - (UINTN)PtrBuf + 1;
+
+  //
+  // The first Buffer..PtrBuf characters are CR, LF, TAB or SPACE.
+  // Now move out all these characters.
+  //
+  while (PtrBuf <= PtrEnd) {
+    *Buffer       = *PtrBuf;
+    Buffer++;
+    PtrBuf++;
+  }
+
+  return;
+}
+
+/**
+  Insert new comment item into comment head.
+
+  @param Buffer          Comment buffer to be added.
+  @param BufferSize      Size of comment buffer.
+  @param CommentHead     Comment Item head entry.
+
+  @retval EFI_OUT_OF_RESOURCES   No enough memory is allocated.
+  @retval EFI_SUCCESS            New comment item is inserted.
+
+**/
+EFI_STATUS
+ProfileGetComments (
+  IN      UINT8                         *Buffer,
+  IN      UINTN                         BufferSize,
+  IN OUT  COMMENT_LINE                  **CommentHead
+  )
+{
+  COMMENT_LINE                          *CommentItem;
+
+  CommentItem = NULL;
+  CommentItem = AllocatePool (sizeof (COMMENT_LINE));
+  if (CommentItem == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  CommentItem->ptrNext  = *CommentHead;
+  *CommentHead          = CommentItem;
+
+  //
+  // Add a trailing '\0'
+  //
+  CommentItem->ptrComment = AllocatePool (BufferSize + 1);
+  if (CommentItem->ptrComment == NULL) {
+    FreePool (CommentItem);
+    return EFI_OUT_OF_RESOURCES;
+  }
+  CopyMem (CommentItem->ptrComment, Buffer, BufferSize);
+  *(CommentItem->ptrComment + BufferSize) = '\0';
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Add new section item into Section head.
+
+  @param Buffer          Section item data buffer.
+  @param BufferSize      Size of section item.
+  @param SectionHead     Section item head entry.
+
+  @retval EFI_OUT_OF_RESOURCES   No enough memory is allocated.
+  @retval EFI_SUCCESS            Section item is NULL or Section item is added.
+
+**/
+EFI_STATUS
+ProfileGetSection (
+  IN      UINT8                         *Buffer,
+  IN      UINTN                         BufferSize,
+  IN OUT  SECTION_ITEM                  **SectionHead
+  )
+{
+  EFI_STATUS                            Status;
+  SECTION_ITEM                          *SectionItem;
+  UINTN                                 Length;
+  UINT8                                 *PtrBuf;
+
+  Status      = EFI_SUCCESS;
+  //
+  // The first character of Buffer is '[', now we want for ']'
+  //
+  PtrBuf      = (UINT8 *)((UINTN)Buffer + BufferSize - 1);
+  while (PtrBuf > Buffer) {
+    if (*PtrBuf == ']') {
+      break;
+    }
+    PtrBuf --;
+  }
+  if (PtrBuf <= Buffer) {
+    //
+    // Not found. Omit this line
+    //
+    return Status;
+  }
+
+  //
+  // excluding the heading '[' and tailing ']'
+  //
+  Length      = PtrBuf - Buffer - 1;
+  ProfileTrim (
+    Buffer + 1,
+    &Length
+  );
+
+  //
+  // omit this line if the section name is null
+  //
+  if (Length == 0) {
+    return Status;
+  }
+
+  SectionItem = AllocatePool (sizeof (SECTION_ITEM));
+  if (SectionItem == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  SectionItem->ptrSection = NULL;
+  SectionItem->SecNameLen = Length;
+  SectionItem->ptrEntry   = NULL;
+  SectionItem->ptrValue   = NULL;
+  SectionItem->ptrNext    = *SectionHead;
+  *SectionHead            = SectionItem;
+
+  //
+  // Add a trailing '\0'
+  //
+  SectionItem->ptrSection = AllocatePool (Length + 1);
+  if (SectionItem->ptrSection == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  //
+  // excluding the heading '['
+  //
+  CopyMem (SectionItem->ptrSection, Buffer + 1, Length);
+  *(SectionItem->ptrSection + Length) = '\0';
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Add new section entry and entry value into Section head.
+
+  @param Buffer          Section entry data buffer.
+  @param BufferSize      Size of section entry.
+  @param SectionHead     Section item head entry.
+
+  @retval EFI_OUT_OF_RESOURCES   No enough memory is allocated.
+  @retval EFI_SUCCESS            Section entry is NULL or Section entry is added.
+
+**/
+EFI_STATUS
+ProfileGetEntry (
+  IN      UINT8                         *Buffer,
+  IN      UINTN                         BufferSize,
+  IN OUT  SECTION_ITEM                  **SectionHead
+  )
+{
+  EFI_STATUS                            Status;
+  SECTION_ITEM                          *SectionItem;
+  SECTION_ITEM                          *PtrSection;
+  UINTN                                 Length;
+  UINT8                                 *PtrBuf;
+  UINT8                                 *PtrEnd;
+
+  Status      = EFI_SUCCESS;
+  PtrBuf      = Buffer;
+  PtrEnd      = (UINT8 *) ((UINTN)Buffer + BufferSize - 1);
+
+  //
+  // First search for '='
+  //
+  while (PtrBuf <= PtrEnd) {
+    if (*PtrBuf == '=') {
+      break;
+    }
+    PtrBuf++;
+  }
+  if (PtrBuf > PtrEnd) {
+    //
+    // Not found. Omit this line
+    //
+    return Status;
+  }
+
+  //
+  // excluding the tailing '='
+  //
+  Length      = PtrBuf - Buffer;
+  ProfileTrim (
+    Buffer,
+    &Length
+  );
+
+  //
+  // Omit this line if the entry name is null
+  //
+  if (Length == 0) {
+    return Status;
+  }
+
+  //
+  // Omit this line if no section header has been found before
+  //
+  if (*SectionHead == NULL) {
+    return Status;
+  }
+  PtrSection  = *SectionHead;
+
+  SectionItem = AllocatePool (sizeof (SECTION_ITEM));
+  if (SectionItem == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  SectionItem->ptrSection = NULL;
+  SectionItem->ptrEntry   = NULL;
+  SectionItem->ptrValue   = NULL;
+  SectionItem->SecNameLen = PtrSection->SecNameLen;
+  SectionItem->ptrNext    = *SectionHead;
+  *SectionHead            = SectionItem;
+
+  //
+  // SectionName, add a trailing '\0'
+  //
+  SectionItem->ptrSection = AllocatePool (PtrSection->SecNameLen + 1);
+  if (SectionItem->ptrSection == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+  CopyMem (SectionItem->ptrSection, PtrSection->ptrSection, PtrSection->SecNameLen + 1);
+
+  //
+  // EntryName, add a trailing '\0'
+  //
+  SectionItem->ptrEntry = AllocatePool (Length + 1);
+  if (SectionItem->ptrEntry == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+  CopyMem (SectionItem->ptrEntry, Buffer, Length);
+  *(SectionItem->ptrEntry + Length) = '\0';
+
+  //
+  // Next search for '#'
+  //
+  PtrBuf      = PtrBuf + 1;
+  Buffer      = PtrBuf;
+  while (PtrBuf <= PtrEnd) {
+    if (*PtrBuf == '#') {
+      break;
+    }
+    PtrBuf++;
+  }
+  Length      = PtrBuf - Buffer;
+  ProfileTrim (
+    Buffer,
+    &Length
+  );
+
+  if (Length > 0) {
+    //
+    // EntryValue, add a trailing '\0'
+    //
+    SectionItem->ptrValue = AllocatePool (Length + 1);
+    if (SectionItem->ptrValue == NULL) {
+      return EFI_OUT_OF_RESOURCES;
+    }
+    CopyMem (SectionItem->ptrValue, Buffer, Length);
+    *(SectionItem->ptrValue + Length) = '\0';
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Free all comment entry and section entry.
+
+  @param Section         Section entry list.
+  @param Comment         Comment entry list.
+
+**/
+VOID
+FreeAllList (
+  IN      SECTION_ITEM                  *Section,
+  IN      COMMENT_LINE                  *Comment
+  )
+{
+  SECTION_ITEM                          *PtrSection;
+  COMMENT_LINE                          *PtrComment;
+
+  while (Section != NULL) {
+    PtrSection    = Section;
+    Section       = Section->ptrNext;
+    if (PtrSection->ptrEntry != NULL) {
+      FreePool (PtrSection->ptrEntry);
+    }
+    if (PtrSection->ptrSection != NULL) {
+      FreePool (PtrSection->ptrSection);
+    }
+    if (PtrSection->ptrValue != NULL) {
+      FreePool (PtrSection->ptrValue);
+    }
+    FreePool (PtrSection);
+  }
+
+  while (Comment != NULL) {
+    PtrComment    = Comment;
+    Comment       = Comment->ptrNext;
+    if (PtrComment->ptrComment != NULL) {
+      FreePool (PtrComment->ptrComment);
+    }
+    FreePool (PtrComment);
+  }
+
+  return;
+}
+
+/**
+  Get section entry value.
+
+  @param Section         Section entry list.
+  @param SectionName     Section name.
+  @param EntryName       Section entry name.
+  @param EntryValue      Point to the got entry value.
+
+  @retval EFI_NOT_FOUND  Section is not found.
+  @retval EFI_SUCCESS    Section entry value is got.
+
+**/
+EFI_STATUS
+UpdateGetProfileString (
+  IN      SECTION_ITEM                  *Section,
+  IN      CHAR8                         *SectionName,
+  IN      CHAR8                         *EntryName,
+  OUT     CHAR8                         **EntryValue
+  )
+{
+  *EntryValue   = NULL;
+
+  while (Section != NULL) {
+    if (AsciiStrCmp ((CONST CHAR8 *) Section->ptrSection, (CONST CHAR8 *) SectionName) == 0) {
+      if (Section->ptrEntry != NULL) {
+        if (AsciiStrCmp ((CONST CHAR8 *) Section->ptrEntry, (CONST CHAR8 *) EntryName) == 0) {
+          break;
+        }
+      }
+    }
+    Section     = Section->ptrNext;
+  }
+
+  if (Section == NULL) {
+    return EFI_NOT_FOUND;
+  }
+
+  *EntryValue   = Section->ptrValue;
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Converts a list of string to a specified buffer.
+
+  @param Buf             The output buffer that contains the string.
+  @param BufferLength    The length of the buffer
+  @param Str             The input string that contains the hex number
+
+  @retval EFI_SUCCESS    The string was successfully converted to the buffer.
+
+**/
+EFI_STATUS
+AsciiStrToBuf (
+  OUT UINT8    *Buf,
+  IN  UINTN    BufferLength,
+  IN  CHAR8    *Str
+  )
+{
+  UINTN       Index;
+  UINTN       StrLength;
+  UINT8       Digit;
+  UINT8       Byte;
+
+  Digit = 0;
+
+  //
+  // Two hex char make up one byte
+  //
+  StrLength = BufferLength * sizeof (CHAR8);
+
+  for(Index = 0; Index < StrLength; Index++, Str++) {
+
+    if ((*Str >= 'a') && (*Str <= 'f')) {
+      Digit = (UINT8) (*Str - 'a' + 0x0A);
+    } else if ((*Str >= 'A') && (*Str <= 'F')) {
+      Digit = (UINT8) (*Str - 'A' + 0x0A);
+    } else if ((*Str >= '0') && (*Str <= '9')) {
+      Digit = (UINT8) (*Str - '0');
+    } else {
+      return EFI_INVALID_PARAMETER;
+    }
+
+    //
+    // For odd characters, write the upper nibble for each buffer byte,
+    // and for even characters, the lower nibble.
+    //
+    if ((Index & 1) == 0) {
+      Byte = (UINT8) (Digit << 4);
+    } else {
+      Byte = Buf[Index / 2];
+      Byte &= 0xF0;
+      Byte = (UINT8) (Byte | Digit);
+    }
+
+    Buf[Index / 2] = Byte;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Converts a string to GUID value.
+  Guid Format is xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
+
+  @param Str              The registry format GUID string that contains the GUID value.
+  @param Guid             A pointer to the converted GUID value.
+
+  @retval EFI_SUCCESS     The GUID string was successfully converted to the GUID value.
+  @retval EFI_UNSUPPORTED The input string is not in registry format.
+  @return others          Some error occurred when converting part of GUID value.
+
+**/
+EFI_STATUS
+AsciiStrToGuid (
+  IN  CHAR8    *Str,
+  OUT EFI_GUID *Guid
+  )
+{
+  //
+  // Get the first UINT32 data
+  //
+  Guid->Data1 = (UINT32) AsciiStrHexToUint64  (Str);
+  while (!IS_HYPHEN (*Str) && !IS_NULL (*Str)) {
+    Str ++;
+  }
+
+  if (IS_HYPHEN (*Str)) {
+    Str++;
+  } else {
+    return EFI_UNSUPPORTED;
+  }
+
+  //
+  // Get the second UINT16 data
+  //
+  Guid->Data2 = (UINT16) AsciiStrHexToUint64  (Str);
+  while (!IS_HYPHEN (*Str) && !IS_NULL (*Str)) {
+    Str ++;
+  }
+
+  if (IS_HYPHEN (*Str)) {
+    Str++;
+  } else {
+    return EFI_UNSUPPORTED;
+  }
+
+  //
+  // Get the third UINT16 data
+  //
+  Guid->Data3 = (UINT16) AsciiStrHexToUint64  (Str);
+  while (!IS_HYPHEN (*Str) && !IS_NULL (*Str)) {
+    Str ++;
+  }
+
+  if (IS_HYPHEN (*Str)) {
+    Str++;
+  } else {
+    return EFI_UNSUPPORTED;
+  }
+
+  //
+  // Get the following 8 bytes data
+  //
+  AsciiStrToBuf (&Guid->Data4[0], 2, Str);
+  //
+  // Skip 2 byte hex chars
+  //
+  Str += 2 * 2;
+
+  if (IS_HYPHEN (*Str)) {
+    Str++;
+  } else {
+    return EFI_UNSUPPORTED;
+  }
+  AsciiStrToBuf (&Guid->Data4[2], 6, Str);
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Pre process config data buffer into Section entry list and Comment entry list.
+
+  @param DataBuffer      Config raw file buffer.
+  @param BufferSize      Size of raw buffer.
+  @param SectionHead     Pointer to the section entry list.
+  @param CommentHead     Pointer to the comment entry list.
+
+  @retval EFI_OUT_OF_RESOURCES  No enough memory is allocated.
+  @retval EFI_SUCCESS           Config data buffer is preprocessed.
+
+**/
+EFI_STATUS
+PreProcessDataFile (
+  IN      UINT8                         *DataBuffer,
+  IN      UINTN                         BufferSize,
+  IN OUT  SECTION_ITEM                  **SectionHead,
+  IN OUT  COMMENT_LINE                  **CommentHead
+  )
+{
+  EFI_STATUS                            Status;
+  CHAR8                                 *Source;
+  CHAR8                                 *CurrentPtr;
+  CHAR8                                 *BufferEnd;
+  CHAR8                                 *PtrLine;
+  UINTN                                 LineLength;
+  UINTN                                 SourceLength;
+  UINTN                                 MaxLineLength;
+
+  *SectionHead          = NULL;
+  *CommentHead          = NULL;
+  BufferEnd             = (CHAR8 *) ( (UINTN) DataBuffer + BufferSize);
+  CurrentPtr            = (CHAR8 *) DataBuffer;
+  MaxLineLength         = MAX_LINE_LENGTH;
+  Status                = EFI_SUCCESS;
+
+  PtrLine = AllocatePool (MaxLineLength);
+  if (PtrLine == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  while (CurrentPtr < BufferEnd) {
+    Source              = CurrentPtr;
+    SourceLength        = (UINTN)BufferEnd - (UINTN)CurrentPtr;
+    LineLength          = MaxLineLength;
+    //
+    // With the assumption that line length is less than 512
+    // characters. Otherwise BUFFER_TOO_SMALL will be returned.
+    //
+    Status              = ProfileGetLine (
+                            (UINT8 *) Source,
+                            SourceLength,
+                            (UINT8 *) PtrLine,
+                            &LineLength
+                            );
+    if (EFI_ERROR (Status)) {
+      if (Status == EFI_BUFFER_TOO_SMALL) {
+        //
+        // If buffer too small, re-allocate the buffer according
+        // to the returned LineLength and try again.
+        //
+        FreePool (PtrLine);
+        PtrLine         = NULL;
+        PtrLine = AllocatePool (LineLength);
+        if (PtrLine == NULL) {
+          Status        = EFI_OUT_OF_RESOURCES;
+          break;
+        }
+        SourceLength    = LineLength;
+        Status          = ProfileGetLine (
+                            (UINT8 *) Source,
+                            SourceLength,
+                            (UINT8 *) PtrLine,
+                            &LineLength
+                            );
+        if (EFI_ERROR (Status)) {
+          break;
+        }
+        MaxLineLength   = LineLength;
+      } else {
+        break;
+      }
+    }
+    CurrentPtr          = (CHAR8 *) ( (UINTN) CurrentPtr + LineLength);
+
+    //
+    // Line got. Trim the line before processing it.
+    //
+    ProfileTrim (
+      (UINT8 *) PtrLine,
+      &LineLength
+   );
+
+    //
+    // Blank line
+    //
+    if (LineLength == 0) {
+      continue;
+    }
+
+    if (PtrLine[0] == '#' || PtrLine[0] == ';') {
+      Status            = ProfileGetComments (
+                            (UINT8 *) PtrLine,
+                            LineLength,
+                            CommentHead
+                            );
+    } else if (PtrLine[0] == '[') {
+      Status            = ProfileGetSection (
+                            (UINT8 *) PtrLine,
+                            LineLength,
+                            SectionHead
+                            );
+    } else {
+      Status            = ProfileGetEntry (
+                            (UINT8 *) PtrLine,
+                            LineLength,
+                            SectionHead
+                            );
+    }
+
+    if (EFI_ERROR (Status)) {
+      break;
+    }
+  }
+
+  //
+  // Free buffer
+  //
+  FreePool (PtrLine);
+
+  return Status;
+}
+
+/**
+  Open an INI config file and return a context.
+
+  @param DataBuffer      Config raw file buffer.
+  @param BufferSize      Size of raw buffer.
+
+  @retval EFI_SUCCESS           Config data buffer is opened and context is returned.
+  @retval EFI_OUT_OF_RESOURCES  No enough memory is allocated.
+**/
+VOID *
+EFIAPI
+OpenDataFile (
+  IN      UINT8                         *DataBuffer,
+  IN      UINTN                         BufferSize
+  )
+{
+  EFI_STATUS                            Status;
+  INI_PARSING_LIB_CONTEXT               *IniContext;
+
+  IniContext = AllocateZeroPool(sizeof(INI_PARSING_LIB_CONTEXT));
+  if (IniContext == NULL) {
+    return NULL;
+  }
+
+  //
+  // First process the data buffer and get all sections and entries
+  //
+  Status = PreProcessDataFile (
+             DataBuffer,
+             BufferSize,
+             &IniContext->SectionHead,
+             &IniContext->CommentHead
+             );
+  if (EFI_ERROR(Status)) {
+    FreePool(IniContext);
+    return NULL;
+  }
+
+  return IniContext;
+}
+
+/**
+  Get section entry string value.
+
+  @param Context         INI Config file context.
+  @param SectionName     Section name.
+  @param EntryName       Section entry name.
+  @param EntryValue      Point to the got entry string value.
+
+  @retval EFI_SUCCESS    Section entry string value is got.
+  @retval EFI_NOT_FOUND  Section is not found.
+**/
+EFI_STATUS
+EFIAPI
+GetStringFromDataFile(
+  IN      VOID                          *Context,
+  IN      CHAR8                         *SectionName,
+  IN      CHAR8                         *EntryName,
+  OUT     CHAR8                         **EntryValue
+  )
+{
+  INI_PARSING_LIB_CONTEXT               *IniContext;
+  EFI_STATUS                            Status;
+
+  IniContext = Context;
+
+  *EntryValue  = NULL;
+  Status = UpdateGetProfileString (
+             IniContext->SectionHead,
+             SectionName,
+             EntryName,
+             EntryValue
+             );
+  return Status;
+}
+
+/**
+  Get section entry GUID value.
+
+  @param Context         INI Config file context.
+  @param SectionName     Section name.
+  @param EntryName       Section entry name.
+  @param Guid            Point to the got GUID value.
+
+  @retval EFI_SUCCESS    Section entry GUID value is got.
+  @retval EFI_NOT_FOUND  Section is not found.
+**/
+EFI_STATUS
+EFIAPI
+GetGuidFromDataFile(
+  IN      VOID                          *Context,
+  IN      CHAR8                         *SectionName,
+  IN      CHAR8                         *EntryName,
+  OUT     EFI_GUID                      *Guid
+  )
+{
+  CHAR8                                 *Value;
+  EFI_STATUS                            Status;
+
+  Status = GetStringFromDataFile(
+             Context,
+             SectionName,
+             EntryName,
+             &Value
+             );
+  if (EFI_ERROR(Status)) {
+    return EFI_NOT_FOUND;
+  }
+
+  Status = AsciiStrToGuid(Value, Guid);
+  if (EFI_ERROR (Status)) {
+    return EFI_NOT_FOUND;
+  }
+  return EFI_SUCCESS;
+}
+
+/**
+  Get section entry decimal UINTN value.
+
+  @param Context         INI Config file context.
+  @param SectionName     Section name.
+  @param EntryName       Section entry name.
+  @param Data            Point to the got decimal UINTN value.
+
+  @retval EFI_SUCCESS    Section entry decimal UINTN value is got.
+  @retval EFI_NOT_FOUND  Section is not found.
+**/
+EFI_STATUS
+EFIAPI
+GetDecimalUintnFromDataFile(
+  IN      VOID                          *Context,
+  IN      CHAR8                         *SectionName,
+  IN      CHAR8                         *EntryName,
+  OUT     UINTN                         *Data
+  )
+{
+  CHAR8                                 *Value;
+  EFI_STATUS                            Status;
+
+  Status = GetStringFromDataFile(
+             Context,
+             SectionName,
+             EntryName,
+             &Value
+             );
+  if (EFI_ERROR(Status)) {
+    return EFI_NOT_FOUND;
+  }
+  *Data = AsciiStrDecimalToUintn(Value);
+  return EFI_SUCCESS;
+}
+
+/**
+  Get section entry heximal UINTN value.
+
+  @param Context         INI Config file context.
+  @param SectionName     Section name.
+  @param EntryName       Section entry name.
+  @param Data            Point to the got heximal UINTN value.
+
+  @retval EFI_SUCCESS    Section entry heximal UINTN value is got.
+  @retval EFI_NOT_FOUND  Section is not found.
+**/
+EFI_STATUS
+EFIAPI
+GetHexUintnFromDataFile(
+  IN      VOID                          *Context,
+  IN      CHAR8                         *SectionName,
+  IN      CHAR8                         *EntryName,
+  OUT     UINTN                         *Data
+  )
+{
+  CHAR8                                 *Value;
+  EFI_STATUS                            Status;
+
+  Status = GetStringFromDataFile(
+             Context,
+             SectionName,
+             EntryName,
+             &Value
+             );
+  if (EFI_ERROR(Status)) {
+    return EFI_NOT_FOUND;
+  }
+  *Data = AsciiStrHexToUintn(Value);
+  return EFI_SUCCESS;
+}
+
+/**
+  Get section entry heximal UINT64 value.
+
+  @param Context         INI Config file context.
+  @param SectionName     Section name.
+  @param EntryName       Section entry name.
+  @param Data            Point to the got heximal UINT64 value.
+
+  @retval EFI_SUCCESS    Section entry heximal UINT64 value is got.
+  @retval EFI_NOT_FOUND  Section is not found.
+**/
+EFI_STATUS
+EFIAPI
+GetHexUint64FromDataFile(
+  IN      VOID                          *Context,
+  IN      CHAR8                         *SectionName,
+  IN      CHAR8                         *EntryName,
+  OUT     UINT64                        *Data
+  )
+{
+  CHAR8                                 *Value;
+  EFI_STATUS                            Status;
+
+  Status = GetStringFromDataFile(
+             Context,
+             SectionName,
+             EntryName,
+             &Value
+             );
+  if (EFI_ERROR(Status)) {
+    return EFI_NOT_FOUND;
+  }
+  *Data = AsciiStrHexToUint64(Value);
+  return EFI_SUCCESS;
+}
+
+/**
+  Close an INI config file and free the context.
+
+  @param Context         INI Config file context.
+**/
+VOID
+EFIAPI
+CloseDataFile(
+  IN      VOID                          *Context
+  )
+{
+  INI_PARSING_LIB_CONTEXT               *IniContext;
+
+  IniContext = Context;
+  FreeAllList(IniContext->SectionHead, IniContext->CommentHead);
+
+  return;
+}
diff --git a/MdeModulePkg/Library/IniParsingLib/IniParsingLib.inf b/MdeModulePkg/Library/IniParsingLib/IniParsingLib.inf
new file mode 100644
index 0000000..4721388
--- /dev/null
+++ b/MdeModulePkg/Library/IniParsingLib/IniParsingLib.inf
@@ -0,0 +1,42 @@
+## @file
+#  INI configuration parsing library.
+#
+#  This library parses the INI configuration file.
+#
+#  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = IniParsingLib
+  MODULE_UNI_FILE                = IniParsingLib.uni
+  FILE_GUID                      = 6E4CD200-43E5-43CE-89E9-D715CF9526C4
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = IniParsingLib
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64 IPF EBC
+#
+
+[Sources]
+  IniParsingLib.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+
+[LibraryClasses]
+  BaseLib
+  BaseMemoryLib
+  DebugLib
+  MemoryAllocationLib
diff --git a/MdeModulePkg/Library/IniParsingLib/IniParsingLib.uni b/MdeModulePkg/Library/IniParsingLib/IniParsingLib.uni
new file mode 100644
index 0000000..9b198e8
--- /dev/null
+++ b/MdeModulePkg/Library/IniParsingLib/IniParsingLib.uni
@@ -0,0 +1,22 @@
+// /** @file
+// INI configuration parsing library.
+//
+// This library parses the INI configuration file.
+//
+// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+//
+// This program and the accompanying materials
+// are licensed and made available under the terms and conditions of the BSD License
+// which accompanies this distribution.  The full text of the license may be found at
+// http://opensource.org/licenses/bsd-license.php
+//
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT             #language en-US "INI configuration parsing library."
+
+#string STR_MODULE_DESCRIPTION          #language en-US "This library parses the INI configuration file."
+
-- 
2.7.4.windows.1



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

* [PATCH 09/45] MdeModulePkg/FmpAuthenticationLib: Add FmpAuthenticationLib instance.
  2016-09-21  6:44 [PATCH 00/45] Add capsule update and recovery sample Jiewen Yao
                   ` (7 preceding siblings ...)
  2016-09-21  6:44 ` [PATCH 08/45] MdeModulePkg/IniParsingLib: Add InitParsingLib instance Jiewen Yao
@ 2016-09-21  6:44 ` Jiewen Yao
  2016-09-21  6:44 ` [PATCH 10/45] MdeModulePkg/DxeCapsuleLibFmp: Add DxeCapsuleLibFmp instance Jiewen Yao
                   ` (39 subsequent siblings)
  48 siblings, 0 replies; 83+ messages in thread
From: Jiewen Yao @ 2016-09-21  6:44 UTC (permalink / raw)
  To: edk2-devel; +Cc: Feng Tian, Star Zeng, Michael D Kinney, Liming Gao, Chao Zhang

This library is used to authenticate a UEFI defined FMP Capsule.

Cc: Feng Tian <feng.tian@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Chao Zhang <chao.b.zhang@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
---
 MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.c   | 274 ++++++++++++++++++++
 MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.inf |  47 ++++
 MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.uni |  22 ++
 3 files changed, 343 insertions(+)

diff --git a/MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.c b/MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.c
new file mode 100644
index 0000000..2accbb4
--- /dev/null
+++ b/MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.c
@@ -0,0 +1,274 @@
+/** @file
+  Provide generic FMP authentication functions for DXE/PEI post memory phase.
+
+  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php.
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Uefi.h>
+
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/FmpAuthenticationLib.h>
+#include <Library/PcdLib.h>
+#include <Protocol/FirmwareManagement.h>
+#include <Guid/SystemResourceTable.h>
+
+#define FMP_AUTHENTICATION_HANDLER_TABLE_SIZE   0x10
+
+UINT64               mMonotonicCount;
+
+UINT32               mNumberOfFmpAuthenticationHandler = 0;
+UINT32               mMaxNumberOfFmpAuthenticationHandler = 0;
+
+GUID                         *mFmpAuthenticationHandlerGuidTable = NULL;
+FMP_AUTHENTICATION_HANDLER   *mFmpAuthenticationHandlerTable = NULL;
+
+/**
+  Reallocates more global memory to store the registered guid and Handler list.
+
+  @retval  RETURN_SUCCESS            Reallocated more global memory space to store guid and function tables.
+  @retval  RETURN_OUT_OF_RESOURCES   Not enough memory to allocate.
+**/
+RETURN_STATUS
+EFIAPI
+ReallocateFmpAuthenticationHandlerTable (
+  )
+{
+  //
+  // Reallocate memory for GuidTable
+  //
+  mFmpAuthenticationHandlerGuidTable = ReallocatePool (
+                                         mMaxNumberOfFmpAuthenticationHandler * sizeof (GUID),
+                                         (mMaxNumberOfFmpAuthenticationHandler + FMP_AUTHENTICATION_HANDLER_TABLE_SIZE) * sizeof (GUID),
+                                         mFmpAuthenticationHandlerGuidTable
+                                         );
+  if (mFmpAuthenticationHandlerGuidTable == NULL) {
+    goto Done;
+  }
+
+  //
+  // Reallocate memory for Authentication handler Table
+  //
+  mFmpAuthenticationHandlerTable = ReallocatePool (
+                                     mMaxNumberOfFmpAuthenticationHandler * sizeof (FMP_AUTHENTICATION_HANDLER),
+                                     (mMaxNumberOfFmpAuthenticationHandler + FMP_AUTHENTICATION_HANDLER_TABLE_SIZE) * sizeof (FMP_AUTHENTICATION_HANDLER),
+                                     mFmpAuthenticationHandlerTable
+                                     );
+  if (mFmpAuthenticationHandlerTable == NULL) {
+    goto Done;
+  }
+
+  //
+  // Increase max handler number
+  //
+  mMaxNumberOfFmpAuthenticationHandler = mMaxNumberOfFmpAuthenticationHandler + FMP_AUTHENTICATION_HANDLER_TABLE_SIZE;
+  return RETURN_SUCCESS;
+
+Done:
+  if (mFmpAuthenticationHandlerGuidTable != NULL) {
+    FreePool (mFmpAuthenticationHandlerGuidTable);
+  }
+  if (mFmpAuthenticationHandlerTable != NULL) {
+    FreePool (mFmpAuthenticationHandlerTable);
+  }
+
+  return RETURN_OUT_OF_RESOURCES;
+}
+
+/**
+  Constructor allocates the global memory to store the registered guid and Handler list.
+
+  @param  ImageHandle   The firmware allocated handle for the EFI image.
+  @param  SystemTable   A pointer to the EFI System Table.
+
+  @retval  RETURN_SUCCESS            Allocated the global memory space to store guid and function tables.
+  @retval  RETURN_OUT_OF_RESOURCES   Not enough memory to allocate.
+**/
+RETURN_STATUS
+EFIAPI
+FmpAuthenticationLibConstructor (
+  VOID
+  )
+{
+  mMonotonicCount = PcdGet64(PcdEdkiiSystemFmpCapsuleMonotonicCount);
+
+  return ReallocateFmpAuthenticationHandlerTable ();
+}
+
+/**
+  Register FMP authentication handler with CertType.
+
+  If CertType is NULL, then ASSERT().
+  If FmpAuthenticationHandler is NULL, then ASSERT().
+
+  @param[in]  CertType                   The certificate type associated with the FMP auth handler.
+  @param[in]  FmpAuthenticationHandler   The FMP authentication handler to be registered.
+
+  @retval  RETURN_SUCCESS           The handlers were registered.
+  @retval  RETURN_OUT_OF_RESOURCES  There are not enough resources available to register the handlers.
+**/
+RETURN_STATUS
+EFIAPI
+RegisterFmpAuthenticationHandler(
+  IN GUID                         *CertType,
+  IN FMP_AUTHENTICATION_HANDLER   FmpAuthenticationHandler
+  )
+{
+  UINTN  Index;
+
+  //
+  // Check input paramter.
+  //
+  ASSERT (CertType != NULL);
+  ASSERT (FmpAuthenticationHandler != NULL);
+
+  //
+  // Search the match registered GetInfo handler for the input guided section.
+  //
+  for (Index = 0; Index < mNumberOfFmpAuthenticationHandler; Index ++) {
+    if (CompareGuid (&mFmpAuthenticationHandlerGuidTable[Index], CertType)) {
+      //
+      // If the guided handler has been registered before, only update its handler.
+      //
+      mFmpAuthenticationHandlerTable[Index] = FmpAuthenticationHandler;
+      return RETURN_SUCCESS;
+    }
+  }
+
+  //
+  // Check the global table is enough to contain new Handler.
+  //
+  if (mNumberOfFmpAuthenticationHandler >= mMaxNumberOfFmpAuthenticationHandler) {
+    if (ReallocateFmpAuthenticationHandlerTable () != RETURN_SUCCESS) {
+      return RETURN_OUT_OF_RESOURCES;
+    }
+  }
+
+  //
+  // Register new Handler and guid value.
+  //
+  CopyGuid (&mFmpAuthenticationHandlerGuidTable [mNumberOfFmpAuthenticationHandler], CertType);
+  mFmpAuthenticationHandlerTable [mNumberOfFmpAuthenticationHandler] = FmpAuthenticationHandler;
+  mNumberOfFmpAuthenticationHandler++;
+
+  return RETURN_SUCCESS;
+}
+
+/**
+  Execute FMP authentication handlers.
+
+  Caution: This function may receive untrusted input.
+
+  If Image is NULL, then ASSERT().
+  If ImageSize is 0, then ASSERT().
+  If LastAttemptStatus is NULL, then ASSERT().
+
+  @param[in]    Image              Points to the new FMP authentication image,
+                                   start from EFI_FIRMWARE_IMAGE_AUTHENTICATION.
+  @param[in]    ImageSize          Size of the authentication image in bytes.
+  @param[out]   LastAttemptStatus  The last attempt status, which will be recorded
+                                   in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+
+  @retval RETURN_SUCCESS            Authentication pass.
+  @retval RETURN_SECURITY_VIOLATION Authentication fail.
+                                    The detail reson is recorded in LastAttemptStatus.
+  @retval RETURN_UNSUPPORTED        No Authentication handler associated with CertType.
+**/
+RETURN_STATUS
+EFIAPI
+ExecuteFmpAuthenticationHandler(
+  IN VOID                         *Image,
+  IN UINTN                        ImageSize,
+  OUT UINT32                      *LastAttemptStatus
+  )
+{
+  EFI_FIRMWARE_IMAGE_AUTHENTICATION         *ImageAuthentication;
+  UINTN                                     ImageOffset;
+  UINTN                                     Index;
+  GUID                                      *CertType;
+
+  //
+  // Check the input parameters
+  //
+  ASSERT (Image != NULL);
+  ASSERT (ImageSize != 0);
+  ASSERT (LastAttemptStatus != NULL);
+
+  ASSERT (mNumberOfFmpAuthenticationHandler != 0);
+
+  ImageAuthentication = (EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image;
+  if (ImageSize < sizeof(EFI_FIRMWARE_IMAGE_AUTHENTICATION)) {
+    DEBUG((DEBUG_ERROR, "ExecuteFmpAuthenticationHandler - ImageSize too small\n"));
+    *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INVALID_FORMAT;
+    return RETURN_SECURITY_VIOLATION;
+  }
+  if (ImageAuthentication->AuthInfo.Hdr.dwLength <= sizeof(WIN_CERTIFICATE) + sizeof(EFI_GUID)) {
+    DEBUG((DEBUG_ERROR, "ExecuteFmpAuthenticationHandler - dwLength too small\n"));
+    *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INVALID_FORMAT;
+    return RETURN_SECURITY_VIOLATION;
+  }
+  if (ImageAuthentication->AuthInfo.Hdr.dwLength > MAX_UINTN - sizeof(UINT64)) {
+    DEBUG((DEBUG_ERROR, "ExecuteFmpAuthenticationHandler - dwLength too big\n"));
+    *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INVALID_FORMAT;
+    return RETURN_SECURITY_VIOLATION;
+  }
+  ImageOffset = sizeof(UINT64) + ImageAuthentication->AuthInfo.Hdr.dwLength;
+  if (ImageSize <= ImageOffset) {
+    DEBUG((DEBUG_ERROR, "ExecuteFmpAuthenticationHandler - ImageSize too small\n"));
+    *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INVALID_FORMAT;
+    return RETURN_SECURITY_VIOLATION;
+  }
+  if (ImageAuthentication->AuthInfo.Hdr.wRevision != 0x0200) {
+    DEBUG((DEBUG_ERROR, "ExecuteFmpAuthenticationHandler - wRevision: 0x%02x, expect - 0x%02x\n", (UINTN)ImageAuthentication->AuthInfo.Hdr.wRevision, (UINTN)0x0200));
+    *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INVALID_FORMAT;
+    return RETURN_SECURITY_VIOLATION;
+  }
+  if (ImageAuthentication->AuthInfo.Hdr.wCertificateType != WIN_CERT_TYPE_EFI_GUID) {
+    DEBUG((DEBUG_ERROR, "ExecuteFmpAuthenticationHandler - wCertificateType: 0x%02x, expect - 0x%02x\n", (UINTN)ImageAuthentication->AuthInfo.Hdr.wCertificateType, (UINTN)WIN_CERT_TYPE_EFI_GUID));
+    *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INVALID_FORMAT;
+    return RETURN_SECURITY_VIOLATION;
+  }
+
+  //
+  // It is used to ensure freshness / no replay.
+  // It is incremented during each firmware image operation.
+  //
+  if (ImageAuthentication->MonotonicCount < mMonotonicCount) {
+    DEBUG((DEBUG_ERROR, "ExecuteFmpAuthenticationHandler - MonotonicCount: 0x%016lx, current - 0x%016lx\n", ImageAuthentication->MonotonicCount, mMonotonicCount));
+    *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INCORRECT_VERSION;
+    return RETURN_SECURITY_VIOLATION;
+  }
+
+  CertType = &ImageAuthentication->AuthInfo.CertType;
+  DEBUG((DEBUG_INFO, "ExecuteFmpAuthenticationHandler - CertType: %g\n", CertType));
+
+  //
+  // Search the match registered extract handler for the input guided section.
+  //
+  for (Index = 0; Index < mNumberOfFmpAuthenticationHandler; Index ++) {
+    if (CompareGuid (&mFmpAuthenticationHandlerGuidTable[Index], CertType)) {
+      //
+      // Call the match handler to extract raw data for the input section data.
+      //
+      return mFmpAuthenticationHandlerTable [Index] (
+               Image,
+               ImageSize,
+               LastAttemptStatus
+               );
+    }
+  }
+
+  //
+  // Not found, the input guided section is not supported.
+  //
+  return RETURN_UNSUPPORTED;
+}
diff --git a/MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.inf b/MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.inf
new file mode 100644
index 0000000..edd0a61
--- /dev/null
+++ b/MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.inf
@@ -0,0 +1,47 @@
+## @file
+# FmpAuthenitcation Library
+#
+# Instance of FmpAuthenitcation Library for DXE/PEI post memory phase.
+#
+# Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+#
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution. The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php.
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = FmpAuthenitcationLib
+  MODULE_UNI_FILE                = FmpAuthenitcationLib.uni
+  FILE_GUID                      = 5011522C-7B0E-4ACB-8E30-9B1D133CF2E0
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = FmpAuthenitcationLib
+  CONSTRUCTOR                    = FmpAuthenticationLibConstructor
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64 IPF EBC
+#
+
+[Sources]
+  FmpAuthenitcationLib.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+  MemoryAllocationLib
+  BaseMemoryLib
+  DebugLib
+  PcdLib
+
+[Pcd]
+  gEfiMdeModulePkgTokenSpaceGuid.PcdEdkiiSystemFmpCapsuleMonotonicCount
diff --git a/MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.uni b/MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.uni
new file mode 100644
index 0000000..ea660c0
--- /dev/null
+++ b/MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.uni
@@ -0,0 +1,22 @@
+// /** @file
+// FmpAuthenitcation Library
+//
+// Instance of FmpAuthenitcation Library for DXE/PEI post memory phase.
+//
+// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+//
+// This program and the accompanying materials
+// are licensed and made available under the terms and conditions of the BSD License
+// which accompanies this distribution.  The full text of the license may be found at
+// http://opensource.org/licenses/bsd-license.php
+//
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT             #language en-US "FmpAuthenitcation Library"
+
+#string STR_MODULE_DESCRIPTION          #language en-US "Instance of FmpAuthenitcation Library for DXE/PEI post memory phase."
+
-- 
2.7.4.windows.1



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

* [PATCH 10/45] MdeModulePkg/DxeCapsuleLibFmp: Add DxeCapsuleLibFmp instance.
  2016-09-21  6:44 [PATCH 00/45] Add capsule update and recovery sample Jiewen Yao
                   ` (8 preceding siblings ...)
  2016-09-21  6:44 ` [PATCH 09/45] MdeModulePkg/FmpAuthenticationLib: Add FmpAuthenticationLib instance Jiewen Yao
@ 2016-09-21  6:44 ` Jiewen Yao
  2016-09-21  6:44 ` [PATCH 11/45] MdeModulePkg/DxeCapsuleLibNull: Add ProcessCapsules() interface Jiewen Yao
                   ` (38 subsequent siblings)
  48 siblings, 0 replies; 83+ messages in thread
From: Jiewen Yao @ 2016-09-21  6:44 UTC (permalink / raw)
  To: edk2-devel; +Cc: Feng Tian, Star Zeng, Michael D Kinney, Liming Gao, Chao Zhang

This instance handles Microsoft UX capsule, UEFI defined device FMP capsule,
and EDKII system FMP capsule.

Cc: Feng Tian <feng.tian@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Chao Zhang <chao.b.zhang@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
---
 MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.c          | 1538 ++++++++++++++++++++
 MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.inf        |   82 ++
 MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.uni        |   22 +
 MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleProcessLib.c   |  517 +++++++
 MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleReportLib.c    |  447 ++++++
 MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleRuntime.c      |  112 ++
 MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf |   85 ++
 MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.uni |   22 +
 8 files changed, 2825 insertions(+)

diff --git a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.c b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.c
new file mode 100644
index 0000000..4cb3044
--- /dev/null
+++ b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.c
@@ -0,0 +1,1538 @@
+/** @file
+  DXE capsule library.
+
+  Caution: This module requires additional review when modified.
+  This module will have external input - capsule image.
+  This external input must be validated carefully to avoid security issue like
+  buffer overflow, integer overflow.
+
+  SupportCapsuleImage(), ProcessCapsuleImage() will receive untrusted input
+  and do basic validation.
+
+  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <PiDxe.h>
+
+#include <IndustryStandard/Bmp.h>
+#include <IndustryStandard/WindowsUxCapsule.h>
+
+#include <Guid/FmpCapsule.h>
+#include <Guid/EdkiiSystemFmpCapsule.h>
+#include <Guid/SystemResourceTable.h>
+#include <Guid/EventGroup.h>
+
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/CapsuleLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/EdkiiSystemCapsuleLib.h>
+#include <Library/UefiLib.h>
+#include <Library/PcdLib.h>
+
+#include <Protocol/GraphicsOutput.h>
+#include <Protocol/EsrtManagement.h>
+#include <Protocol/FirmwareManagement.h>
+#include <Protocol/DevicePath.h>
+
+EFI_SYSTEM_RESOURCE_TABLE *mEsrtTable              = NULL;
+BOOLEAN                   mIsVirtualAddrConverted  = FALSE;
+BOOLEAN                   mDxeCapsuleLibEndOfDxe   = FALSE;
+
+GUID      *mEdkiiSystemFmpCapsuleImageTypeIdGuid;
+UINTN     mEdkiiSystemFmpCapsuleImageTypeIdGuidCount;
+
+/**
+  Initialize capsule related variables.
+**/
+VOID
+InitCapsuleVariable(
+  VOID
+  );
+
+/**
+  Check if this FMP capsule is recorded.
+
+  @param CapsuleHeader  The capsule image header
+  @param PayloadIndex   FMP payload index
+  @param ImageHeader    FMP image header
+
+  @retval TRUE  This FMP capsule is recorded.
+  @retval FALSE This FMP capsule is not recorded.
+**/
+BOOLEAN
+IsFmpCapsuleVariableRecorded(
+  IN EFI_CAPSULE_HEADER                           *CapsuleHeader,
+  IN UINTN                                        PayloadIndex,
+  IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader
+  );
+
+/**
+  Record capsule status variable.
+
+  @param CapsuleHeader  The capsule image header
+  @param CapsuleStatus  The capsule process stauts
+
+  @retval EFI_SUCCESS          The capsule status variable is recorded.
+  @retval EFI_OUT_OF_RESOURCES No resource to record the capsule status variable.
+**/
+EFI_STATUS
+RecordCapsuleStatusVariable(
+  IN EFI_CAPSULE_HEADER                           *CapsuleHeader,
+  IN EFI_STATUS                                   CapsuleStatus
+  );
+
+/**
+  Record FMP capsule status variable.
+
+  @param CapsuleHeader  The capsule image header
+  @param CapsuleStatus  The capsule process stauts
+  @param PayloadIndex   FMP payload index
+  @param ImageHeader    FMP image header
+
+  @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
+  );
+
+/**
+  Function indicate the current completion progress of the firmware
+  update. Platform may override with own specific progress function.
+
+  @param  Completion    A value between 1 and 100 indicating the current completion progress of the firmware update
+
+  @retval EFI_SUCESS    Input capsule is a correct FMP capsule.
+**/
+EFI_STATUS
+EFIAPI
+Update_Image_Progress (
+  IN UINTN Completion
+  )
+{
+  return EFI_SUCCESS;
+}
+
+/**
+  Return if this FMP is a system FMP or a device FMP, based upon FmpImageInfo.
+
+  @param[in] FmpImageHeader A pointer to EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
+
+  @retval TRUE  It is a system FMP.
+  @retval FALSE It is a device FMP.
+**/
+BOOLEAN
+IsSystemFmpImage (
+  IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER   *FmpImageHeader
+  )
+{
+  GUID      *Guid;
+  UINTN     Count;
+  UINTN     Index;
+
+  Guid = mEdkiiSystemFmpCapsuleImageTypeIdGuid;
+  Count = mEdkiiSystemFmpCapsuleImageTypeIdGuidCount;
+
+  for (Index = 0; Index < Count; Index++, Guid++) {
+    if (CompareGuid(&FmpImageHeader->UpdateImageTypeId, Guid)) {
+      return TRUE;
+    }
+  }
+
+  return FALSE;
+}
+
+/**
+  Return if this CapsuleGuid is a FMP capsule GUID or not.
+
+  @param[in] CapsuleGuid A pointer to EFI_GUID
+
+  @retval TRUE  It is a FMP capsule GUID.
+  @retval FALSE It is not a FMP capsule GUID.
+**/
+BOOLEAN
+IsFmpCapsuleGuid(
+  IN EFI_GUID  *CapsuleGuid
+  )
+{
+  if (CompareGuid(&gEfiFmpCapsuleGuid, CapsuleGuid)) {
+    return TRUE;
+  }
+
+  return FALSE;
+}
+
+/**
+  This function assumes the input Capusule image already passes basic check in
+  ValidateFmpCapsule().
+
+  Criteria of system FMP capsule is:
+  1) FmpCapsuleHeader->EmbeddedDriverCount is 0.
+  2) FmpCapsuleHeader->PayloadItemCount is not 0.
+  3) All ImageHeader->UpdateImageTypeId matches PcdEdkiiSystemFmpCapsuleImageTypeIdGuid.
+
+  @param  CapsuleHeader    Points to a capsule header.
+
+  @retval TRUE   Input capsule is a correct system FMP capsule.
+  @retval FALSE  Input capsule is not a correct system FMP capsule.
+**/
+BOOLEAN
+IsSystemFmpCapsuleImage (
+  IN EFI_CAPSULE_HEADER *CapsuleHeader
+  )
+{
+  EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER       *FmpCapsuleHeader;
+  EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader;
+  UINT64                                       *ItemOffsetList;
+  UINT32                                       ItemNum;
+  UINTN                                        Index;
+
+  FmpCapsuleHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *) ((UINT8 *) CapsuleHeader + CapsuleHeader->HeaderSize);
+
+  if (FmpCapsuleHeader->EmbeddedDriverCount != 0) {
+    return FALSE;
+  }
+
+  if (FmpCapsuleHeader->PayloadItemCount == 0) {
+    return FALSE;
+  }
+
+  ItemNum = FmpCapsuleHeader->EmbeddedDriverCount + FmpCapsuleHeader->PayloadItemCount;
+
+  ItemOffsetList = (UINT64 *)(FmpCapsuleHeader + 1);
+
+  for (Index = 0; Index < ItemNum; Index++) {
+    ImageHeader  = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *)((UINT8 *)FmpCapsuleHeader + ItemOffsetList[Index]);
+    if (!IsSystemFmpImage(ImageHeader)) {
+      return FALSE;
+    }
+  }
+
+  return TRUE;
+}
+
+/**
+  Validate if it is valid capsule header
+
+  Caution: This function may receive untrusted input.
+
+  This function assumes the caller provided correct CapsuleHeader pointer
+  and CapsuleSize.
+
+  This function validates the fields in EFI_CAPSULE_HEADER.
+
+  @param  CapsuleHeader    Points to a capsule header.
+  @param  CapsuleSize      Size of the whole capsule image.
+
+**/
+BOOLEAN
+IsValidCapsuleHeader(
+  IN EFI_CAPSULE_HEADER  *CapsuleHeader,
+  IN UINT64              CapsuleSize
+  )
+{
+  if (CapsuleHeader->CapsuleImageSize != CapsuleSize) {
+    return FALSE;
+  }
+  if (CapsuleHeader->HeaderSize >= CapsuleHeader->CapsuleImageSize) {
+    return FALSE;
+  }
+  return TRUE;
+}
+
+/**
+  Validate Fmp capsules layout.
+
+  Caution: This function may receive untrusted input.
+
+  This function assumes the caller validated the capsule by using
+  IsValidCapsuleHeader(), so that all fields in EFI_CAPSULE_HEADER are correct.
+  The capsule buffer size is CapsuleHeader->CapsuleImageSize.
+
+  This function validates the fields in EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
+  and EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER.
+
+  This function need support nested FMP capsule.
+
+  @param[in]   CapsuleHeader        Points to a capsule header.
+  @param[out]  IsSystemFmp          If it is a system FMP.
+  @param[out]  EmbeddedDriverCount  The EmbeddedDriverCount in the FMP capsule.
+
+  @retval EFI_SUCESS             Input capsule is a correct FMP capsule.
+  @retval EFI_INVALID_PARAMETER  Input capsule is not a correct FMP capsule.
+**/
+EFI_STATUS
+ValidateFmpCapsule (
+  IN EFI_CAPSULE_HEADER *CapsuleHeader,
+  OUT BOOLEAN           *IsSystemFmp, OPTIONAL
+  OUT UINT16            *EmbeddedDriverCount OPTIONAL
+  )
+{
+  EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER       *FmpCapsuleHeader;
+  UINT8                                        *EndOfCapsule;
+  EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader;
+  UINT8                                        *EndOfPayload;
+  UINT64                                       *ItemOffsetList;
+  UINT32                                       ItemNum;
+  UINTN                                        Index;
+  UINTN                                        FmpCapsuleSize;
+  UINTN                                        FmpCapsuleHeaderSize;
+  UINT64                                       FmpImageSize;
+  UINTN                                        FmpImageHeaderSize;
+
+  if (!IsFmpCapsuleGuid(&CapsuleHeader->CapsuleGuid)) {
+    return ValidateFmpCapsule ((EFI_CAPSULE_HEADER *)((UINTN)CapsuleHeader + CapsuleHeader->HeaderSize), IsSystemFmp, EmbeddedDriverCount);
+  }
+
+  if (CapsuleHeader->HeaderSize >= CapsuleHeader->CapsuleImageSize) {
+    DEBUG((EFI_D_ERROR, "HeaderSize(0x%x) >= CapsuleImageSize(0x%x)\n", CapsuleHeader->HeaderSize, CapsuleHeader->CapsuleImageSize));
+    return EFI_INVALID_PARAMETER;
+  }
+
+  FmpCapsuleHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *) ((UINT8 *) CapsuleHeader + CapsuleHeader->HeaderSize);
+  EndOfCapsule     = (UINT8 *) CapsuleHeader + CapsuleHeader->CapsuleImageSize;
+  FmpCapsuleSize   = (UINTN)EndOfCapsule - (UINTN)FmpCapsuleHeader;
+
+  if (FmpCapsuleSize < sizeof(EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER)) {
+    DEBUG((EFI_D_ERROR, "FmpCapsuleSize(0x%x) < EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER\n", FmpCapsuleSize));
+    return EFI_INVALID_PARAMETER;
+  }
+
+  // Check EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
+  if (FmpCapsuleHeader->Version != EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION) {
+    DEBUG((EFI_D_ERROR, "FmpCapsuleHeader->Version(0x%x) != EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION\n", FmpCapsuleHeader->Version));
+    return EFI_INVALID_PARAMETER;
+  }
+  ItemOffsetList = (UINT64 *)(FmpCapsuleHeader + 1);
+
+  // No overflow
+  ItemNum = FmpCapsuleHeader->EmbeddedDriverCount + FmpCapsuleHeader->PayloadItemCount;
+
+  if ((FmpCapsuleSize - sizeof(EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER))/sizeof(UINT64) < ItemNum) {
+    DEBUG((EFI_D_ERROR, "ItemNum(0x%x) too big\n", ItemNum));
+    return EFI_INVALID_PARAMETER;
+  }
+  FmpCapsuleHeaderSize = sizeof(EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER) + sizeof(UINT64)*ItemNum;
+
+  // Check ItemOffsetList
+  for (Index = 0; Index < ItemNum; Index++) {
+    if (ItemOffsetList[Index] >= FmpCapsuleSize) {
+      DEBUG((EFI_D_ERROR, "ItemOffsetList[%d](0x%lx) >= FmpCapsuleSize(0x%x)\n", Index, ItemOffsetList[Index], FmpCapsuleSize));
+      return EFI_INVALID_PARAMETER;
+    }
+    if (ItemOffsetList[Index] < FmpCapsuleHeaderSize) {
+      DEBUG((EFI_D_ERROR, "ItemOffsetList[%d](0x%lx) < FmpCapsuleHeaderSize(0x%x)\n", Index, ItemOffsetList[Index], FmpCapsuleHeaderSize));
+      return EFI_INVALID_PARAMETER;
+    }
+    //
+    // All the address in ItemOffsetList must be stored in ascending order
+    //
+    if (Index > 0) {
+      if (ItemOffsetList[Index] <= ItemOffsetList[Index - 1]) {
+        DEBUG((EFI_D_ERROR, "ItemOffsetList[%d](0x%lx) < ItemOffsetList[%d](0x%x)\n", Index, ItemOffsetList[Index], Index, ItemOffsetList[Index - 1]));
+        return EFI_INVALID_PARAMETER;
+      }
+    }
+  }
+
+  // Check EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
+  for (Index = FmpCapsuleHeader->EmbeddedDriverCount; Index < ItemNum; Index++) {
+    ImageHeader  = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *)((UINT8 *)FmpCapsuleHeader + ItemOffsetList[Index]);
+    if (Index == ItemNum - 1) {
+      EndOfPayload = (UINT8 *)((UINTN)EndOfCapsule - (UINTN)FmpCapsuleHeader);
+    } else {
+      EndOfPayload = (UINT8 *)(UINTN)ItemOffsetList[Index+1];
+    }
+    FmpImageSize = (UINTN)EndOfPayload - ItemOffsetList[Index];
+
+    if (FmpImageSize < OFFSET_OF(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER, UpdateHardwareInstance)) {
+      DEBUG((EFI_D_ERROR, "FmpImageSize(0x%lx) < EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER\n", FmpImageSize));
+      return EFI_INVALID_PARAMETER;
+    }
+    FmpImageHeaderSize = sizeof(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER);
+    if ((ImageHeader->Version > EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) ||
+        (ImageHeader->Version < 1)) {
+      DEBUG((EFI_D_ERROR, "ImageHeader->Version(0x%x) Unknown\n", ImageHeader->Version));
+      return EFI_INVALID_PARAMETER;
+    }
+    if (ImageHeader->Version < EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {
+      FmpImageHeaderSize = OFFSET_OF(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER, UpdateHardwareInstance);
+    }
+
+    // No overflow
+    if (FmpImageSize != (UINT64)FmpImageHeaderSize + (UINT64)ImageHeader->UpdateImageSize + (UINT64)ImageHeader->UpdateVendorCodeSize) {
+      DEBUG((EFI_D_ERROR, "FmpImageSize(0x%lx) mismatch, UpdateImageSize(0x%x) UpdateVendorCodeSize(0x%x)\n", FmpImageSize, ImageHeader->UpdateImageSize, ImageHeader->UpdateVendorCodeSize));
+      return EFI_INVALID_PARAMETER;
+    }
+  }
+
+  if (ItemNum == 0) {
+    //
+    // No driver & payload element in FMP
+    //
+    EndOfPayload = (UINT8 *)(FmpCapsuleHeader + 1);
+    if (EndOfPayload != EndOfCapsule) {
+      DEBUG((EFI_D_ERROR, "EndOfPayload(0x%x) mismatch, EndOfCapsule(0x%x)\n", EndOfPayload, EndOfCapsule));
+      return EFI_INVALID_PARAMETER;
+    }
+    return EFI_UNSUPPORTED;
+  }
+
+  //
+  // Check in system FMP capsule
+  //
+  if (IsSystemFmp != NULL) {
+    *IsSystemFmp = IsSystemFmpCapsuleImage(CapsuleHeader);
+  }
+
+  if (EmbeddedDriverCount != NULL) {
+    *EmbeddedDriverCount = FmpCapsuleHeader->EmbeddedDriverCount;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Convert a *.BMP graphics image to a GOP blt buffer. If a NULL Blt buffer
+  is passed in a GopBlt buffer will be allocated by this routine. If a GopBlt
+  buffer is passed in it will be used if it is big enough.
+
+  @param  BmpImage      Pointer to BMP file
+  @param  BmpImageSize  Number of bytes in BmpImage
+  @param  GopBlt        Buffer containing GOP version of BmpImage.
+  @param  GopBltSize    Size of GopBlt in bytes.
+  @param  PixelHeight   Height of GopBlt/BmpImage in pixels
+  @param  PixelWidth    Width of GopBlt/BmpImage in pixels
+
+  @retval EFI_SUCCESS           GopBlt and GopBltSize are returned.
+  @retval EFI_UNSUPPORTED       BmpImage is not a valid *.BMP image
+  @retval EFI_BUFFER_TOO_SMALL  The passed in GopBlt buffer is not big enough.
+                                GopBltSize will contain the required size.
+  @retval EFI_OUT_OF_RESOURCES  No enough buffer to allocate.
+
+**/
+STATIC
+EFI_STATUS
+ConvertBmpToGopBlt (
+  IN     VOID      *BmpImage,
+  IN     UINTN     BmpImageSize,
+  IN OUT VOID      **GopBlt,
+  IN OUT UINTN     *GopBltSize,
+     OUT UINTN     *PixelHeight,
+     OUT UINTN     *PixelWidth
+  )
+{
+  UINT8                         *Image;
+  UINT8                         *ImageHeader;
+  BMP_IMAGE_HEADER              *BmpHeader;
+  BMP_COLOR_MAP                 *BmpColorMap;
+  EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer;
+  EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;
+  UINT64                        BltBufferSize;
+  UINTN                         Index;
+  UINTN                         Height;
+  UINTN                         Width;
+  UINTN                         ImageIndex;
+  UINT32                        DataSizePerLine;
+  BOOLEAN                       IsAllocated;
+  UINT32                        ColorMapNum;
+
+  if (sizeof (BMP_IMAGE_HEADER) > BmpImageSize) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  BmpHeader = (BMP_IMAGE_HEADER *) BmpImage;
+
+  if (BmpHeader->CharB != 'B' || BmpHeader->CharM != 'M') {
+    return EFI_UNSUPPORTED;
+  }
+
+  //
+  // Doesn't support compress.
+  //
+  if (BmpHeader->CompressionType != 0) {
+    return EFI_UNSUPPORTED;
+  }
+
+  //
+  // Only support BITMAPINFOHEADER format.
+  // BITMAPFILEHEADER + BITMAPINFOHEADER = BMP_IMAGE_HEADER
+  //
+  if (BmpHeader->HeaderSize != sizeof (BMP_IMAGE_HEADER) - OFFSET_OF(BMP_IMAGE_HEADER, HeaderSize)) {
+    return EFI_UNSUPPORTED;
+  }
+
+  //
+  // The data size in each line must be 4 byte alignment.
+  //
+  DataSizePerLine = ((BmpHeader->PixelWidth * BmpHeader->BitPerPixel + 31) >> 3) & (~0x3);
+  BltBufferSize = MultU64x32 (DataSizePerLine, BmpHeader->PixelHeight);
+  if (BltBufferSize > (UINT32) ~0) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if ((BmpHeader->Size != BmpImageSize) ||
+      (BmpHeader->Size < BmpHeader->ImageOffset) ||
+      (BmpHeader->Size - BmpHeader->ImageOffset !=  BmpHeader->PixelHeight * DataSizePerLine)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // Calculate Color Map offset in the image.
+  //
+  Image       = BmpImage;
+  BmpColorMap = (BMP_COLOR_MAP *) (Image + sizeof (BMP_IMAGE_HEADER));
+  if (BmpHeader->ImageOffset < sizeof (BMP_IMAGE_HEADER)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (BmpHeader->ImageOffset > sizeof (BMP_IMAGE_HEADER)) {
+    switch (BmpHeader->BitPerPixel) {
+      case 1:
+        ColorMapNum = 2;
+        break;
+      case 4:
+        ColorMapNum = 16;
+        break;
+      case 8:
+        ColorMapNum = 256;
+        break;
+      default:
+        ColorMapNum = 0;
+        break;
+      }
+    //
+    // BMP file may has padding data between the bmp header section and the bmp data section.
+    //
+    if (BmpHeader->ImageOffset - sizeof (BMP_IMAGE_HEADER) < sizeof (BMP_COLOR_MAP) * ColorMapNum) {
+      return EFI_INVALID_PARAMETER;
+    }
+  }
+
+  //
+  // Calculate graphics image data address in the image
+  //
+  Image         = ((UINT8 *) BmpImage) + BmpHeader->ImageOffset;
+  ImageHeader   = Image;
+
+  //
+  // Calculate the BltBuffer needed size.
+  //
+  BltBufferSize = MultU64x32 ((UINT64) BmpHeader->PixelWidth, BmpHeader->PixelHeight);
+  //
+  // Ensure the BltBufferSize * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) doesn't overflow
+  //
+  if (BltBufferSize > DivU64x32 ((UINTN) ~0, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL))) {
+    return EFI_UNSUPPORTED;
+  }
+  BltBufferSize = MultU64x32 (BltBufferSize, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
+
+  IsAllocated   = FALSE;
+  if (*GopBlt == NULL) {
+    //
+    // GopBlt is not allocated by caller.
+    //
+    *GopBltSize = (UINTN) BltBufferSize;
+    *GopBlt     = AllocatePool (*GopBltSize);
+    IsAllocated = TRUE;
+    if (*GopBlt == NULL) {
+      return EFI_OUT_OF_RESOURCES;
+    }
+  } else {
+    //
+    // GopBlt has been allocated by caller.
+    //
+    if (*GopBltSize < (UINTN) BltBufferSize) {
+      *GopBltSize = (UINTN) BltBufferSize;
+      return EFI_BUFFER_TOO_SMALL;
+    }
+  }
+
+  *PixelWidth   = BmpHeader->PixelWidth;
+  *PixelHeight  = BmpHeader->PixelHeight;
+
+  //
+  // Convert image from BMP to Blt buffer format
+  //
+  BltBuffer = *GopBlt;
+  for (Height = 0; Height < BmpHeader->PixelHeight; Height++) {
+    Blt = &BltBuffer[(BmpHeader->PixelHeight - Height - 1) * BmpHeader->PixelWidth];
+    for (Width = 0; Width < BmpHeader->PixelWidth; Width++, Image++, Blt++) {
+      switch (BmpHeader->BitPerPixel) {
+      case 1:
+        //
+        // Convert 1-bit (2 colors) BMP to 24-bit color
+        //
+        for (Index = 0; Index < 8 && Width < BmpHeader->PixelWidth; Index++) {
+          Blt->Red    = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Red;
+          Blt->Green  = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Green;
+          Blt->Blue   = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Blue;
+          Blt++;
+          Width++;
+        }
+
+        Blt--;
+        Width--;
+        break;
+
+      case 4:
+        //
+        // Convert 4-bit (16 colors) BMP Palette to 24-bit color
+        //
+        Index       = (*Image) >> 4;
+        Blt->Red    = BmpColorMap[Index].Red;
+        Blt->Green  = BmpColorMap[Index].Green;
+        Blt->Blue   = BmpColorMap[Index].Blue;
+        if (Width < (BmpHeader->PixelWidth - 1)) {
+          Blt++;
+          Width++;
+          Index       = (*Image) & 0x0f;
+          Blt->Red    = BmpColorMap[Index].Red;
+          Blt->Green  = BmpColorMap[Index].Green;
+          Blt->Blue   = BmpColorMap[Index].Blue;
+        }
+        break;
+
+      case 8:
+        //
+        // Convert 8-bit (256 colors) BMP Palette to 24-bit color
+        //
+        Blt->Red    = BmpColorMap[*Image].Red;
+        Blt->Green  = BmpColorMap[*Image].Green;
+        Blt->Blue   = BmpColorMap[*Image].Blue;
+        break;
+
+      case 24:
+        //
+        // It is 24-bit BMP.
+        //
+        Blt->Blue   = *Image++;
+        Blt->Green  = *Image++;
+        Blt->Red    = *Image;
+        break;
+
+      case 32:
+        //
+        // it is 32-bit BMP. Skip pixel's highest byte
+        //
+        Blt->Blue  = *Image++;
+        Blt->Green = *Image++;
+        Blt->Red   = *Image++;
+        break;
+
+      default:
+        //
+        // Other bit format BMP is not supported.
+        //
+        if (IsAllocated) {
+          FreePool (*GopBlt);
+          *GopBlt = NULL;
+        }
+        return EFI_UNSUPPORTED;
+      };
+
+    }
+
+    ImageIndex = (UINTN) (Image - ImageHeader);
+    if ((ImageIndex % 4) != 0) {
+      //
+      // Bmp Image starts each row on a 32-bit boundary!
+      //
+      Image = Image + (4 - (ImageIndex % 4));
+    }
+  }
+
+  return EFI_SUCCESS;
+}
+
+
+/**
+  Those capsules supported by the firmwares.
+
+  @param  CapsuleHeader    Points to a capsule header.
+
+  @retval EFI_SUCESS       Input capsule is supported by firmware.
+  @retval EFI_UNSUPPORTED  Input capsule is not supported by the firmware.
+**/
+EFI_STATUS
+DisplayCapsuleImage (
+  IN EFI_CAPSULE_HEADER  *CapsuleHeader
+  )
+{
+  DISPLAY_DISPLAY_PAYLOAD       *ImagePayload;
+  UINTN                         PayloadSize;
+  EFI_STATUS                    Status;
+  EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;
+  UINTN                         BltSize;
+  UINTN                         Height;
+  UINTN                         Width;
+  EFI_GRAPHICS_OUTPUT_PROTOCOL  *GraphicsOutput;
+
+  ImagePayload = (DISPLAY_DISPLAY_PAYLOAD *)(CapsuleHeader + 1);
+  PayloadSize = (UINTN)(CapsuleHeader->CapsuleImageSize - sizeof(EFI_CAPSULE_HEADER));
+
+  if (ImagePayload->Version != 1) {
+    return EFI_UNSUPPORTED;
+  }
+  if (CalculateCheckSum8((UINT8 *)CapsuleHeader, CapsuleHeader->CapsuleImageSize) != 0) {
+    return EFI_UNSUPPORTED;
+  }
+  //
+  // Only Support Bitmap by now
+  //
+  if (ImagePayload->ImageType != 0) {
+    return EFI_UNSUPPORTED;
+  }
+
+  //
+  // Try to open GOP
+  //
+  Status = gBS->HandleProtocol (gST->ConsoleOutHandle, &gEfiGraphicsOutputProtocolGuid, (VOID **)&GraphicsOutput);
+  if (EFI_ERROR (Status)) {
+    Status = gBS->LocateProtocol(&gEfiGraphicsOutputProtocolGuid, NULL, (VOID **)&GraphicsOutput);
+    if (EFI_ERROR(Status)) {
+      return EFI_UNSUPPORTED;
+    }
+  }
+
+  if (GraphicsOutput->Mode->Mode != ImagePayload->Mode) {
+    return EFI_UNSUPPORTED;
+  }
+
+  Blt = NULL;
+  Width = 0;
+  Height = 0;
+  Status = ConvertBmpToGopBlt (
+             ImagePayload + 1,
+             PayloadSize - sizeof(DISPLAY_DISPLAY_PAYLOAD),
+             (VOID **)&Blt,
+             &BltSize,
+             &Height,
+             &Width
+             );
+
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Status = GraphicsOutput->Blt (
+                             GraphicsOutput,
+                             Blt,
+                             EfiBltBufferToVideo,
+                             0,
+                             0,
+                             (UINTN) ImagePayload->OffsetX,
+                             (UINTN) ImagePayload->OffsetY,
+                             Width,
+                             Height,
+                             Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
+                             );
+
+  FreePool(Blt);
+
+  return Status;
+}
+
+/**
+  Dump FMP information.
+
+  @param ImageInfoSize       The size of ImageInfo, in bytes.
+  @param ImageInfo           A pointer to EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+  @param DescriptorVersion   The version of EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+  @param DescriptorCount     The count of EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+  @param DescriptorSize      The size of an individual EFI_FIRMWARE_IMAGE_DESCRIPTOR, in bytes.
+  @param PackageVersion      The version of package.
+  @param PackageVersionName  The version name of package.
+**/
+VOID
+DumpFmpImageInfo(
+  IN UINTN                           ImageInfoSize,
+  IN EFI_FIRMWARE_IMAGE_DESCRIPTOR   *ImageInfo,
+  IN UINT32                          DescriptorVersion,
+  IN UINT8                           DescriptorCount,
+  IN UINTN                           DescriptorSize,
+  IN UINT32                          PackageVersion,
+  IN CHAR16                          *PackageVersionName
+  )
+{
+  EFI_FIRMWARE_IMAGE_DESCRIPTOR                 *CurrentImageInfo;
+  UINTN                                         Index;
+
+  DEBUG((DEBUG_VERBOSE, "  DescriptorVersion  - 0x%x\n", DescriptorVersion));
+  DEBUG((DEBUG_VERBOSE, "  DescriptorCount    - 0x%x\n", DescriptorCount));
+  DEBUG((DEBUG_VERBOSE, "  DescriptorSize     - 0x%x\n", DescriptorSize));
+  DEBUG((DEBUG_VERBOSE, "  PackageVersion     - 0x%x\n", PackageVersion));
+  DEBUG((DEBUG_VERBOSE, "  PackageVersionName - %s\n\n", PackageVersionName));
+  CurrentImageInfo = ImageInfo;
+  for (Index = 0; Index < DescriptorCount; Index++) {
+    DEBUG((DEBUG_VERBOSE, "  ImageDescriptor (%d)\n", Index));
+    DEBUG((DEBUG_VERBOSE, "    ImageIndex                  - 0x%x\n", CurrentImageInfo->ImageIndex));
+    DEBUG((DEBUG_VERBOSE, "    ImageTypeId                 - %g\n", &CurrentImageInfo->ImageTypeId));
+    DEBUG((DEBUG_VERBOSE, "    ImageId                     - 0x%lx\n", CurrentImageInfo->ImageId));
+    DEBUG((DEBUG_VERBOSE, "    ImageIdName                 - %s\n", CurrentImageInfo->ImageIdName));
+    DEBUG((DEBUG_VERBOSE, "    Version                     - 0x%x\n", CurrentImageInfo->Version));
+    DEBUG((DEBUG_VERBOSE, "    VersionName                 - %s\n", CurrentImageInfo->VersionName));
+    DEBUG((DEBUG_VERBOSE, "    Size                        - 0x%x\n", CurrentImageInfo->Size));
+    DEBUG((DEBUG_VERBOSE, "    AttributesSupported         - 0x%lx\n", CurrentImageInfo->AttributesSupported));
+    DEBUG((DEBUG_VERBOSE, "    AttributesSetting           - 0x%lx\n", CurrentImageInfo->AttributesSetting));
+    DEBUG((DEBUG_VERBOSE, "    Compatibilities             - 0x%lx\n", CurrentImageInfo->Compatibilities));
+    if (DescriptorVersion > 1) {
+      DEBUG((DEBUG_VERBOSE, "    LowestSupportedImageVersion - 0x%x\n", CurrentImageInfo->LowestSupportedImageVersion));
+      if (DescriptorVersion > 2) {
+        DEBUG((DEBUG_VERBOSE, "    LastAttemptVersion          - 0x%x\n", CurrentImageInfo->LastAttemptVersion));
+        DEBUG((DEBUG_VERBOSE, "    LastAttemptStatus           - 0x%x\n", CurrentImageInfo->LastAttemptStatus));
+        DEBUG((DEBUG_VERBOSE, "    HardwareInstance            - 0x%lx\n", CurrentImageInfo->HardwareInstance));
+      }
+    }
+    //
+    // Use DescriptorSize to move ImageInfo Pointer to stay compatible with different ImageInfo version
+    //
+    CurrentImageInfo = (EFI_FIRMWARE_IMAGE_DESCRIPTOR *)((UINT8 *)CurrentImageInfo + DescriptorSize);
+  }
+}
+
+/**
+  Dump a non-nested FMP capsule.
+
+  @param  CapsuleHeader  A pointer to CapsuleHeader
+**/
+VOID
+DumpFmpCapsule(
+  IN EFI_CAPSULE_HEADER                *CapsuleHeader
+  )
+{
+  EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER        *FmpCapsuleHeader;
+  EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER  *ImageHeader;
+  UINTN                                         Index;
+  UINT64                                        *ItemOffsetList;
+
+  FmpCapsuleHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *)((UINT8 *)CapsuleHeader + CapsuleHeader->HeaderSize);
+
+  DEBUG((DEBUG_VERBOSE, "FmpCapsule:\n"));
+  DEBUG((DEBUG_VERBOSE, "  Version                - 0x%x\n", FmpCapsuleHeader->Version));
+  DEBUG((DEBUG_VERBOSE, "  EmbeddedDriverCount    - 0x%x\n", FmpCapsuleHeader->EmbeddedDriverCount));
+  DEBUG((DEBUG_VERBOSE, "  PayloadItemCount       - 0x%x\n", FmpCapsuleHeader->PayloadItemCount));
+
+  ItemOffsetList = (UINT64 *)(FmpCapsuleHeader + 1);
+  for (Index = 0; Index < FmpCapsuleHeader->EmbeddedDriverCount; Index++) {
+    DEBUG((DEBUG_VERBOSE, "  ItemOffsetList[%d]      - 0x%lx\n", Index, ItemOffsetList[Index]));
+  }
+  for (; Index < (UINTN)(FmpCapsuleHeader->EmbeddedDriverCount + FmpCapsuleHeader->PayloadItemCount); Index++) {
+    DEBUG((DEBUG_VERBOSE, "  ItemOffsetList[%d]      - 0x%lx\n", Index, ItemOffsetList[Index]));
+    ImageHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *)((UINT8 *)FmpCapsuleHeader + ItemOffsetList[Index]);
+
+    DEBUG((DEBUG_VERBOSE, "  ImageHeader:\n"));
+    DEBUG((DEBUG_VERBOSE, "    Version                - 0x%x\n", ImageHeader->Version));
+    DEBUG((DEBUG_VERBOSE, "    UpdateImageTypeId      - %g\n", &ImageHeader->UpdateImageTypeId));
+    DEBUG((DEBUG_VERBOSE, "    UpdateImageIndex       - 0x%x\n", ImageHeader->UpdateImageIndex));
+    DEBUG((DEBUG_VERBOSE, "    UpdateImageSize        - 0x%x\n", ImageHeader->UpdateImageSize));
+    DEBUG((DEBUG_VERBOSE, "    UpdateVendorCodeSize   - 0x%x\n", ImageHeader->UpdateVendorCodeSize));
+    if (ImageHeader->Version >= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {
+      DEBUG((DEBUG_VERBOSE, "    UpdateHardwareInstance - 0x%lx\n", ImageHeader->UpdateHardwareInstance));
+    }
+  }
+}
+
+/**
+  Process System Firmware management protocol data capsule.
+
+  This function assumes the caller validated the capsule by using
+  ValidateFmpCapsule(), so that all fields in EFI_CAPSULE_HEADER,
+  EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER and
+  EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER are correct.
+
+  This function assumes nested FMP capsule is handled by ProcessFmpCapsuleImage.
+
+  @param  CapsuleHeader         Points to a capsule header.
+
+  @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.
+  @retval EFI_OUT_OF_RESOURCES  Not enough memory.
+**/
+EFI_STATUS
+DispatchSystemFmpImages (
+  IN EFI_CAPSULE_HEADER *CapsuleHeader
+  )
+{
+  UINTN                                         Length;
+  VOID                                          *Image;
+  EFI_STATUS                                    Status;
+  VOID                                          *AuthenticatedImage;
+  UINTN                                         AuthenticatedImageSize;
+  UINT32                                        LastAttemptVersion;
+  UINT32                                        LastAttemptStatus;
+  VOID                                          *DispatchFvImage;
+  UINTN                                         DispatchFvImageSize;
+  EFI_HANDLE                                    FvProtocolHandle;
+  EFI_FIRMWARE_VOLUME_HEADER                    *FvImage;
+  BOOLEAN                                       Result;
+  UINTN                                         ItemIndex;
+  EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER        *FmpCapsuleHeader;
+  EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER  *ImageHeader;
+  UINT64                                        *ItemOffsetList;
+
+  DEBUG((EFI_D_INFO, "DispatchSystemFmpImages\n"));
+
+  FmpCapsuleHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *)((UINT8 *)CapsuleHeader + CapsuleHeader->HeaderSize);
+  ItemOffsetList = (UINT64 *)(FmpCapsuleHeader + 1);
+
+  for (ItemIndex = 0; ItemIndex < FmpCapsuleHeader->PayloadItemCount; ItemIndex++) {
+    ImageHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *)((UINT8 *)FmpCapsuleHeader + ItemOffsetList[ItemIndex]);
+    if (ImageHeader->Version >= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {
+      Image = (UINT8 *)(ImageHeader + 1);
+    } else {
+      //
+      // If the EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER is version 1, only match ImageTypeId.
+      // Header should exclude UpdateHardwareInstance field
+      //
+      Image = (UINT8 *)ImageHeader + OFFSET_OF(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER, UpdateHardwareInstance);
+    }
+    Length = ImageHeader->UpdateImageSize;
+
+    //
+    // Verify
+    //
+    Status = CapsuleAuthenticateSystemFirmware(Image, Length, FALSE, &LastAttemptVersion, &LastAttemptStatus, &AuthenticatedImage, &AuthenticatedImageSize);
+    if (EFI_ERROR(Status)) {
+      DEBUG((EFI_D_INFO, "BiosAuthenticateImage - %r\n", Status));
+      return Status;
+    }
+
+    //
+    // Get FV
+    //
+    Result = ExtractDriverFvImage(AuthenticatedImage, AuthenticatedImageSize, &DispatchFvImage, &DispatchFvImageSize);
+    if (Result) {
+      DEBUG((EFI_D_INFO, "ExtractDriverFvImage\n"));
+      //
+      // Dispatch
+      //
+      if (((EFI_FIRMWARE_VOLUME_HEADER *)DispatchFvImage)->FvLength == DispatchFvImageSize) {
+        FvImage = AllocatePages(EFI_SIZE_TO_PAGES(DispatchFvImageSize));
+        if (FvImage != NULL) {
+          CopyMem(FvImage, DispatchFvImage, DispatchFvImageSize);
+          Status = gDS->ProcessFirmwareVolume(
+                          (VOID *)FvImage,
+                          (UINTN)FvImage->FvLength,
+                          &FvProtocolHandle
+                          );
+          DEBUG((EFI_D_INFO, "ProcessFirmwareVolume - %r\n", Status));
+          if (!EFI_ERROR(Status)) {
+            gDS->Dispatch();
+            DEBUG((EFI_D_INFO, "Dispatch Done\n"));
+          }
+        }
+      }
+    }
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Process Firmware management protocol data capsule.
+
+  This function assumes the caller validated the capsule by using
+  ValidateFmpCapsule(), so that all fields in EFI_CAPSULE_HEADER,
+  EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER and
+  EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER are correct.
+
+  This function need support nested FMP capsule.
+
+  @param  CapsuleHeader         Points to a capsule header.
+  @param  IsSystemFmp           If this capsule is a system FMP capsule.
+
+  @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.
+  @retval EFI_OUT_OF_RESOURCES  Not enough memory.
+**/
+EFI_STATUS
+ProcessFmpCapsuleImage (
+  IN EFI_CAPSULE_HEADER *CapsuleHeader,
+  IN BOOLEAN            IsSystemFmp
+  )
+{
+  EFI_STATUS                                    Status;
+  EFI_STATUS                                    StatusEsrt;
+  EFI_STATUS                                    StatusRet;
+  EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER        *FmpCapsuleHeader;
+  EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER  *ImageHeader;
+  UINT8                                         *Image;
+  EFI_HANDLE                                    ImageHandle;
+  UINT64                                        *ItemOffsetList;
+  UINT32                                        ItemNum;
+  UINTN                                         Index;
+  UINTN                                         ExitDataSize;
+  EFI_HANDLE                                    *HandleBuffer;
+  EFI_FIRMWARE_MANAGEMENT_PROTOCOL              *Fmp;
+  UINTN                                         NumberOfHandles;
+  UINTN                                         DescriptorSize;
+  UINT8                                         FmpImageInfoCount;
+  UINT32                                        FmpImageInfoDescriptorVer;
+  UINTN                                         ImageInfoSize;
+  UINT32                                        PackageVersion;
+  CHAR16                                        *PackageVersionName;
+  CHAR16                                        *AbortReason;
+  EFI_FIRMWARE_IMAGE_DESCRIPTOR                 *FmpImageInfoBuf;
+  EFI_FIRMWARE_IMAGE_DESCRIPTOR                 *TempFmpImageInfo;
+  UINTN                                         DriverLen;
+  UINTN                                         Index1;
+  UINTN                                         Index2;
+  MEMMAP_DEVICE_PATH                            MemMapNode;
+  EFI_DEVICE_PATH_PROTOCOL                      *DriverDevicePath;
+  ESRT_MANAGEMENT_PROTOCOL                      *EsrtProtocol;
+  EFI_SYSTEM_RESOURCE_ENTRY                     EsrtEntry;
+  VOID                                          *VendorCode;
+
+  if (!IsFmpCapsuleGuid(&CapsuleHeader->CapsuleGuid)) {
+    return ProcessFmpCapsuleImage ((EFI_CAPSULE_HEADER *)((UINTN)CapsuleHeader + CapsuleHeader->HeaderSize), IsSystemFmp);
+  }
+
+  Status           = EFI_SUCCESS;
+  StatusRet        = EFI_NOT_FOUND;
+  HandleBuffer     = NULL;
+  ExitDataSize     = 0;
+  DriverDevicePath = NULL;
+  EsrtProtocol     = NULL;
+
+  DumpFmpCapsule(CapsuleHeader);
+
+  FmpCapsuleHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *) ((UINT8 *) CapsuleHeader + CapsuleHeader->HeaderSize);
+
+  if (FmpCapsuleHeader->Version > EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION) {
+    return EFI_INVALID_PARAMETER;
+  }
+  ItemOffsetList = (UINT64 *)(FmpCapsuleHeader + 1);
+
+  ItemNum = FmpCapsuleHeader->EmbeddedDriverCount + FmpCapsuleHeader->PayloadItemCount;
+
+  //
+  // capsule in which driver count and payload count are both zero is not processed.
+  //
+  if (ItemNum == 0) {
+    return EFI_SUCCESS;
+  }
+
+  //
+  // Update corresponding ESRT entry LastAttemp Status
+  //
+  Status = gBS->LocateProtocol(&gEsrtManagementProtocolGuid, NULL, (VOID **)&EsrtProtocol);
+  if (EFI_ERROR (Status)) {
+    EsrtProtocol = NULL;
+  }
+
+  //
+  // 1. For system FMP, the images are insides of FmpPayload
+  //
+  if (IsSystemFmp) {
+    Status = DispatchSystemFmpImages(CapsuleHeader);
+    if (EFI_ERROR(Status)) {
+      return Status;
+    }
+  }
+
+  //
+  // 2. Try to load & start all the drivers within capsule
+  //
+  SetDevicePathNodeLength (&MemMapNode.Header, sizeof (MemMapNode));
+  MemMapNode.Header.Type     = HARDWARE_DEVICE_PATH;
+  MemMapNode.Header.SubType  = HW_MEMMAP_DP;
+  MemMapNode.MemoryType      = EfiBootServicesCode;
+  MemMapNode.StartingAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)CapsuleHeader;
+  MemMapNode.EndingAddress   = (EFI_PHYSICAL_ADDRESS)(UINTN)((UINT8 *)CapsuleHeader + CapsuleHeader->CapsuleImageSize - 1);
+
+  DriverDevicePath = AppendDevicePathNode (NULL, &MemMapNode.Header);
+  if (DriverDevicePath == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  for (Index = 0; Index < FmpCapsuleHeader->EmbeddedDriverCount; Index++) {
+    if (FmpCapsuleHeader->PayloadItemCount == 0 && Index == (UINTN)FmpCapsuleHeader->EmbeddedDriverCount - 1) {
+      //
+      // When driver is last element in the ItemOffsetList array, the driver size is calculated by reference CapsuleImageSize in EFI_CAPSULE_HEADER
+      //
+      DriverLen = CapsuleHeader->CapsuleImageSize - CapsuleHeader->HeaderSize - (UINTN)ItemOffsetList[Index];
+    } else {
+      DriverLen = (UINTN)ItemOffsetList[Index + 1] - (UINTN)ItemOffsetList[Index];
+    }
+
+    DEBUG((EFI_D_INFO, "FmpCapsule: LoadImage ...\n"));
+    Status = gBS->LoadImage(
+                    FALSE,
+                    gImageHandle,
+                    DriverDevicePath,
+                    (UINT8 *)FmpCapsuleHeader + ItemOffsetList[Index],
+                    DriverLen,
+                    &ImageHandle
+                    );
+    DEBUG((EFI_D_INFO, "FmpCapsule: LoadImage - %r\n", Status));
+    if (EFI_ERROR(Status)) {
+      StatusRet = Status;
+      goto EXIT;
+    }
+
+    DEBUG((EFI_D_INFO, "FmpCapsule: StartImage ...\n"));
+    Status = gBS->StartImage(
+                    ImageHandle,
+                    &ExitDataSize,
+                    NULL
+                    );
+    DEBUG((EFI_D_INFO, "FmpCapsule: StartImage - %r\n", Status));
+    if (EFI_ERROR(Status)) {
+      DEBUG ((DEBUG_ERROR, "Driver Return Status = %r\n", Status));
+      StatusRet = Status;
+      goto EXIT;
+    }
+  }
+
+  //
+  // 3. Route payload to right FMP instance
+  //
+  DEBUG((EFI_D_INFO, "FmpCapsule: route payload to right FMP instance ...\n"));
+
+  Status = gBS->LocateHandleBuffer (
+                  ByProtocol,
+                  &gEfiFirmwareManagementProtocolGuid,
+                  NULL,
+                  &NumberOfHandles,
+                  &HandleBuffer
+                  );
+
+  if (!EFI_ERROR(Status)) {
+    for(Index1 = 0; Index1 < NumberOfHandles; Index1++) {
+      Status = gBS->HandleProtocol(
+                      HandleBuffer[Index1],
+                      &gEfiFirmwareManagementProtocolGuid,
+                      (VOID **)&Fmp
+                      );
+      if (EFI_ERROR(Status)) {
+        continue;
+      }
+
+      ImageInfoSize = 0;
+      Status = Fmp->GetImageInfo (
+                      Fmp,
+                      &ImageInfoSize,
+                      NULL,
+                      NULL,
+                      NULL,
+                      NULL,
+                      NULL,
+                      NULL
+                      );
+      if (Status != EFI_BUFFER_TOO_SMALL) {
+        continue;
+      }
+
+      FmpImageInfoBuf = NULL;
+      FmpImageInfoBuf = AllocateZeroPool (ImageInfoSize);
+      if (FmpImageInfoBuf == NULL) {
+        StatusRet = EFI_OUT_OF_RESOURCES;
+        goto EXIT;
+      }
+
+      PackageVersionName = NULL;
+      Status = Fmp->GetImageInfo (
+                      Fmp,
+                      &ImageInfoSize,               // ImageInfoSize
+                      FmpImageInfoBuf,              // ImageInfo
+                      &FmpImageInfoDescriptorVer,   // DescriptorVersion
+                      &FmpImageInfoCount,           // DescriptorCount
+                      &DescriptorSize,              // DescriptorSize
+                      &PackageVersion,              // PackageVersion
+                      &PackageVersionName           // PackageVersionName
+                      );
+
+      //
+      // If FMP GetInformation interface failed, skip this resource
+      //
+      if (EFI_ERROR(Status)) {
+        FreePool(FmpImageInfoBuf);
+        continue;
+      }
+
+      DEBUG((EFI_D_INFO, "FMP (%d) ImageInfo:\n", Index));
+      DumpFmpImageInfo(
+        ImageInfoSize,               // ImageInfoSize
+        FmpImageInfoBuf,             // ImageInfo
+        FmpImageInfoDescriptorVer,   // DescriptorVersion
+        FmpImageInfoCount,           // DescriptorCount
+        DescriptorSize,              // DescriptorSize
+        PackageVersion,              // PackageVersion
+        PackageVersionName           // PackageVersionName
+        );
+
+      if (PackageVersionName != NULL) {
+        FreePool(PackageVersionName);
+      }
+
+      TempFmpImageInfo = FmpImageInfoBuf;
+      for (Index2 = 0; Index2 < FmpImageInfoCount; Index2++) {
+        //
+        // Check all the payload entry in capsule payload list
+        //
+        for (Index = FmpCapsuleHeader->EmbeddedDriverCount; Index < ItemNum; Index++) {
+          ImageHeader  = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *)((UINT8 *)FmpCapsuleHeader + ItemOffsetList[Index]);
+
+          if (IsFmpCapsuleVariableRecorded(CapsuleHeader, Index - FmpCapsuleHeader->EmbeddedDriverCount, ImageHeader)) {
+            DEBUG((EFI_D_INFO, "FMP Capsule already processed (%g):", CapsuleHeader));
+            DEBUG((EFI_D_INFO, "ImageTypeId - %g, ", ImageHeader->UpdateImageTypeId));
+            DEBUG((EFI_D_INFO, "PayloadIndex - 0x%x, ImageIndex - 0x%x\n", Index - FmpCapsuleHeader->EmbeddedDriverCount, ImageHeader->UpdateImageIndex));
+            continue;
+          }
+
+          if (CompareGuid(&ImageHeader->UpdateImageTypeId, &TempFmpImageInfo->ImageTypeId) &&
+              ImageHeader->UpdateImageIndex == TempFmpImageInfo->ImageIndex) {
+            AbortReason = NULL;
+            if (ImageHeader->Version >= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {
+              if(ImageHeader->UpdateHardwareInstance != 0){
+                //
+                // FMP Version is >=2 & UpdateHardwareInstance Skip 2 case
+                //  1. FMP Image info Version < 3
+                //  2. HardwareInstance doesn't match
+                //
+                if (FmpImageInfoDescriptorVer < EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION ||
+                   ImageHeader->UpdateHardwareInstance != TempFmpImageInfo->HardwareInstance) {
+                  continue;
+                }
+              }
+              Image = (UINT8 *)(ImageHeader + 1);
+            } else {
+              //
+              // If the EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER is version 1, only match ImageTypeId.
+              // Header should exclude UpdateHardwareInstance field
+              //
+              Image = (UINT8 *)ImageHeader + OFFSET_OF(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER, UpdateHardwareInstance);
+            }
+
+            if (ImageHeader->UpdateVendorCodeSize == 0) {
+              VendorCode = NULL;
+            } else {
+              VendorCode = Image + ImageHeader->UpdateImageSize;
+            }
+            DEBUG((EFI_D_INFO, "Fmp->SetImage ...\n"));
+            Status = Fmp->SetImage(
+                            Fmp,
+                            ImageHeader->UpdateImageIndex,          // ImageIndex
+                            Image,                                  // Image
+                            ImageHeader->UpdateImageSize,           // ImageSize
+                            VendorCode,                                   // VendorCode
+                            Update_Image_Progress,                  // Progress
+                            &AbortReason                            // AbortReason
+                            );
+            DEBUG((EFI_D_INFO, "Fmp->SetImage - %r\n", Status));
+            if (AbortReason != NULL) {
+              DEBUG ((EFI_D_ERROR, "%s\n", AbortReason));
+              FreePool(AbortReason);
+            }
+            RecordFmpCapsuleStatusVariable(
+              CapsuleHeader,                                 // CapsuleGuid
+              Status,                                        // CapsuleStatus
+              Index - FmpCapsuleHeader->EmbeddedDriverCount, // PayloadIndex
+              ImageHeader                                    // ImageHeader
+              );
+            if (StatusRet != EFI_SUCCESS) {
+              StatusRet = Status;
+            }
+            //
+            // Update EsrtEntry For V1, V2 FMP instance. V3 FMP ESRT cache will be synced up through EsrtSyncFmp interface
+            //
+            if (FmpImageInfoDescriptorVer < EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION && EsrtProtocol != NULL) {
+               StatusEsrt = EsrtProtocol->GetEsrtEntry(&TempFmpImageInfo->ImageTypeId, &EsrtEntry);
+               if (!EFI_ERROR(StatusEsrt)){
+                 if (!EFI_ERROR(Status)) {
+                   EsrtEntry.LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;
+                 } else {
+                   EsrtEntry.LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL;
+                 }
+                 EsrtEntry.LastAttemptVersion = 0;
+                 EsrtProtocol->UpdateEsrtEntry(&EsrtEntry);
+               }
+             }
+          }
+        }
+        //
+        // Use DescriptorSize to move ImageInfo Pointer to stay compatible with different ImageInfo version
+        //
+        TempFmpImageInfo = (EFI_FIRMWARE_IMAGE_DESCRIPTOR *)((UINT8 *)TempFmpImageInfo + DescriptorSize);
+      }
+      FreePool(FmpImageInfoBuf);
+    }
+  }
+
+EXIT:
+
+  if (HandleBuffer != NULL) {
+    FreePool(HandleBuffer);
+  }
+
+  if (DriverDevicePath != NULL) {
+    FreePool(DriverDevicePath);
+  }
+
+  return StatusRet;
+}
+
+/**
+  Return if there is a FMP header below capsule header.
+
+  @param[in] CapsuleHeader A pointer to EFI_CAPSULE_HEADER
+
+  @retval TRUE  There is a FMP header below capsule header.
+  @retval FALSE There is not a FMP header below capsule header
+**/
+BOOLEAN
+IsNestedFmpCapsule(
+  IN EFI_CAPSULE_HEADER         *CapsuleHeader
+  )
+{
+  EFI_STATUS                 Status;
+  EFI_SYSTEM_RESOURCE_TABLE  *Esrt;
+  EFI_SYSTEM_RESOURCE_ENTRY  *EsrtEntry;
+  UINTN                      Index;
+  BOOLEAN                    EsrtGuidFound;
+  EFI_CAPSULE_HEADER         *NestedCapsuleHeader;
+  UINTN                      NestedCapsuleSize;
+  ESRT_MANAGEMENT_PROTOCOL   *EsrtProtocol;
+  EFI_SYSTEM_RESOURCE_ENTRY  Entry;
+
+  EsrtGuidFound = FALSE;
+
+  //
+  // Check ESRT protocol
+  //
+  Status = gBS->LocateProtocol(&gEsrtManagementProtocolGuid, NULL, (VOID **)&EsrtProtocol);
+  if (!EFI_ERROR(Status)) {
+    Status = EsrtProtocol->GetEsrtEntry(&CapsuleHeader->CapsuleGuid, &Entry);
+    if (!EFI_ERROR(Status)) {
+      EsrtGuidFound = TRUE;
+    }
+  }
+
+  //
+  // Check ESRT configuration table
+  //
+  if (!EsrtGuidFound) {
+    Status = EfiGetSystemConfigurationTable(&gEfiSystemResourceTableGuid, (VOID **)&Esrt);
+    if (!EFI_ERROR(Status)) {
+      EsrtEntry = (VOID *)(Esrt + 1);
+      for (Index = 0; Index < Esrt->FwResourceCount; Index++, EsrtEntry++) {
+        if (CompareGuid(&EsrtEntry->FwClass, &CapsuleHeader->CapsuleGuid)) {
+          EsrtGuidFound = TRUE;
+          break;
+        }
+      }
+    }
+  }
+  if (!EsrtGuidFound) {
+    return FALSE;
+  }
+
+  //
+  // Check nested capsule header
+  // FMP GUID after ESRT one
+  //
+  NestedCapsuleHeader = (EFI_CAPSULE_HEADER *)((UINT8 *)CapsuleHeader + CapsuleHeader->HeaderSize);
+  NestedCapsuleSize = (UINTN)CapsuleHeader + CapsuleHeader->CapsuleImageSize - (UINTN)NestedCapsuleHeader;
+  if (NestedCapsuleSize < sizeof(EFI_CAPSULE_HEADER)) {
+    return FALSE;
+  }
+  if (!IsValidCapsuleHeader(NestedCapsuleHeader, NestedCapsuleSize)) {
+    return FALSE;
+  }
+  if (!IsFmpCapsuleGuid(&NestedCapsuleHeader->CapsuleGuid)) {
+    return FALSE;
+  }
+  DEBUG ((EFI_D_INFO, "IsNestedFmpCapsule\n"));
+  return TRUE;
+}
+
+/**
+  Return if this FMP is a system FMP or a device FMP, based upon CapsuleHeader.
+
+  @param[in] CapsuleHeader A pointer to EFI_CAPSULE_HEADER
+
+  @retval TRUE  It is a system FMP.
+  @retval FALSE It is a device FMP.
+**/
+BOOLEAN
+IsFmpCapsule(
+  IN EFI_CAPSULE_HEADER         *CapsuleHeader
+  )
+{
+  if (IsFmpCapsuleGuid(&CapsuleHeader->CapsuleGuid)) {
+    return TRUE;
+  }
+  if (IsNestedFmpCapsule(CapsuleHeader)) {
+    return TRUE;
+  }
+  return FALSE;
+}
+
+/**
+  Those capsules supported by the firmwares.
+
+  Caution: This function may receive untrusted input.
+
+  @param  CapsuleHeader    Points to a capsule header.
+
+  @retval EFI_SUCESS       Input capsule is supported by firmware.
+  @retval EFI_UNSUPPORTED  Input capsule is not supported by the firmware.
+  @retval EFI_INVALID_PARAMETER Input capsule layout is not correct
+**/
+EFI_STATUS
+EFIAPI
+SupportCapsuleImage (
+  IN EFI_CAPSULE_HEADER *CapsuleHeader
+  )
+{
+  //
+  // check Display Capsule Guid
+  //
+  if (CompareGuid (&gWindowsUxCapsuleGuid, &CapsuleHeader->CapsuleGuid)) {
+    return EFI_SUCCESS;
+  }
+
+  if (IsFmpCapsule(CapsuleHeader)) {
+    //
+    // Check layout of FMP capsule
+    //
+    return ValidateFmpCapsule(CapsuleHeader, NULL, NULL);
+  }
+  DEBUG((EFI_D_ERROR, "Unknown Capsule Guid - %g\n", &CapsuleHeader->CapsuleGuid));
+  return EFI_UNSUPPORTED;
+}
+
+/**
+  The firmware implements to process the capsule image.
+
+  Caution: This function may receive untrusted input.
+
+  @param  CapsuleHeader         Points to a capsule header.
+
+  @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.
+  @retval EFI_OUT_OF_RESOURCES  Not enough memory.
+**/
+EFI_STATUS
+EFIAPI
+ProcessCapsuleImage (
+  IN EFI_CAPSULE_HEADER *CapsuleHeader
+  )
+{
+  EFI_STATUS                   Status;
+  BOOLEAN                      IsSystemFmp;
+
+  if (SupportCapsuleImage (CapsuleHeader) != EFI_SUCCESS) {
+    return EFI_UNSUPPORTED;
+  }
+
+  //
+  // Display image in firmware update display capsule
+  //
+  if (CompareGuid (&gWindowsUxCapsuleGuid, &CapsuleHeader->CapsuleGuid)) {
+    DEBUG((EFI_D_INFO, "ProcessCapsuleImage for WindowsUxCapsule ...\n"));
+    Status = DisplayCapsuleImage(CapsuleHeader);
+    RecordCapsuleStatusVariable(CapsuleHeader, Status);
+    return Status;
+  }
+
+  //
+  // Check FMP capsule layout
+  //
+  if (IsFmpCapsule (CapsuleHeader)) {
+    DEBUG((EFI_D_INFO, "ProcessCapsuleImage for FmpCapsule ...\n"));
+    DEBUG((EFI_D_INFO, "ValidateFmpCapsule ...\n"));
+    Status = ValidateFmpCapsule(CapsuleHeader, &IsSystemFmp, NULL);
+    DEBUG((EFI_D_INFO, "ValidateFmpCapsule - %r\n", Status));
+    if (EFI_ERROR(Status)) {
+      return Status;
+    }
+
+    //
+    // Press EFI FMP Capsule
+    //
+    DEBUG((EFI_D_INFO, "ProcessFmpCapsuleImage ...\n"));
+    Status = ProcessFmpCapsuleImage(CapsuleHeader, IsSystemFmp);
+    DEBUG((EFI_D_INFO, "ProcessFmpCapsuleImage - %r\n", Status));
+
+    return Status;
+  }
+
+  return EFI_UNSUPPORTED;
+}
+
+/**
+  Callback function executed when the EndOfDxe event group is signaled.
+
+  @param[in] Event      Event whose notification function is being invoked.
+  @param[in] Context    The pointer to the notification function's context, which
+                        is implementation-dependent.
+**/
+VOID
+EFIAPI
+DxeCapsuleLibEndOfDxe(
+  IN EFI_EVENT  Event,
+  IN VOID       *Context
+  )
+{
+  mDxeCapsuleLibEndOfDxe = TRUE;
+}
+
+/**
+  The constructor function.
+
+  @param  ImageHandle   The firmware allocated handle for the EFI image.
+  @param  SystemTable   A pointer to the EFI System Table.
+
+  @retval EFI_SUCCESS   The constructor successfully .
+**/
+EFI_STATUS
+EFIAPI
+DxeCapsuleLibConstructor(
+  IN EFI_HANDLE         ImageHandle,
+  IN EFI_SYSTEM_TABLE   *SystemTable
+  )
+{
+  EFI_EVENT     EndOfDxeEvent;
+  EFI_STATUS    Status;
+
+  mEdkiiSystemFmpCapsuleImageTypeIdGuidCount = PcdGetSize(PcdEdkiiSystemFmpCapsuleImageTypeIdGuid) / sizeof(GUID);
+  mEdkiiSystemFmpCapsuleImageTypeIdGuid = AllocateCopyPool(mEdkiiSystemFmpCapsuleImageTypeIdGuidCount * sizeof(GUID), PcdGetPtr(PcdEdkiiSystemFmpCapsuleImageTypeIdGuid));
+  ASSERT(mEdkiiSystemFmpCapsuleImageTypeIdGuid != NULL);
+
+  Status = gBS->CreateEventEx (
+                  EVT_NOTIFY_SIGNAL,
+                  TPL_CALLBACK,
+                  DxeCapsuleLibEndOfDxe,
+                  NULL,
+                  &gEfiEndOfDxeEventGroupGuid,
+                  &EndOfDxeEvent
+                  );
+  ASSERT_EFI_ERROR (Status);
+
+  InitCapsuleVariable();
+
+  return EFI_SUCCESS;
+}
diff --git a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.inf b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.inf
new file mode 100644
index 0000000..e957b7b
--- /dev/null
+++ b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.inf
@@ -0,0 +1,82 @@
+## @file
+#  Capsule library instance for DXE_DRIVER.
+#
+#  Capsule library instance for DXE_DRIVER module types.
+#
+#  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = DxeCapsuleLib
+  MODULE_UNI_FILE                = DxeCapsuleLib.uni
+  FILE_GUID                      = 534E35DE-8EB3-47b3-A4E0-72A571E50733
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = CapsuleLib|DXE_DRIVER UEFI_APPLICATION
+  CONSTRUCTOR                    = DxeCapsuleLibConstructor
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64 IPF EBC
+#
+
+[Sources]
+  DxeCapsuleLib.c
+  DxeCapsuleProcessLib.c
+  DxeCapsuleReportLib.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+  BaseLib
+  BaseMemoryLib
+  DebugLib
+  MemoryAllocationLib
+  DxeServicesTableLib
+  UefiBootServicesTableLib
+  DevicePathLib
+  ReportStatusCodeLib
+  PrintLib
+  HobLib
+  EdkiiSystemCapsuleLib
+
+[Pcd]
+  gEfiMdeModulePkgTokenSpaceGuid.PcdEdkiiSystemFmpCapsuleImageTypeIdGuid  ## CONSUMES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleMax
+  gEfiMdeModulePkgTokenSpaceGuid.PcdSystemRebootAfterCapsuleProcessFlag
+
+  gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeSubClassCapsule
+  gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleStatusCodeProcessCapsulesBegin
+  gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleStatusCodeProcessCapsulesEnd
+  gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleStatusCodeUpdatingFirmware
+  gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleStatusCodeUpdateFirmwareSuccess
+  gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleStatusCodeUpdateFirmwareFailed
+  gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleStatusCodeResettingSystem
+
+[Protocols]
+  gEsrtManagementProtocolGuid             ## CONSUMES
+  gEfiFirmwareManagementProtocolGuid      ## SOMETIMES_CONSUMES
+  gEdkiiVariableLockProtocolGuid          ## SOMETIMES_CONSUMES
+
+[Guids]
+  gEfiFmpCapsuleGuid                      ## SOMETIMES_CONSUMES ## GUID
+  gWindowsUxCapsuleGuid                   ## SOMETIMES_CONSUMES ## GUID
+  gEfiSystemResourceTableGuid             ## SOMETIMES_CONSUMES ## GUID
+  gEfiCapsuleReportGuid                   ## CONSUMES ## Variable
+  gEfiCapsuleVendorGuid                   ## CONSUMES ## Variable
+  gEfiEndOfDxeEventGroupGuid              ## CONSUMES ## Event
+
+[Depex]
+  gEfiVariableWriteArchProtocolGuid
diff --git a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.uni b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.uni
new file mode 100644
index 0000000..05a80d0
--- /dev/null
+++ b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.uni
@@ -0,0 +1,22 @@
+// /** @file
+// Capsule library instance for DXE_DRIVER.
+//
+// Capsule library instance for DXE_DRIVER module types.
+//
+// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+//
+// This program and the accompanying materials
+// are licensed and made available under the terms and conditions of the BSD License
+// which accompanies this distribution.  The full text of the license may be found at
+// http://opensource.org/licenses/bsd-license.php
+//
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT             #language en-US "Capsule Support Library"
+
+#string STR_MODULE_DESCRIPTION          #language en-US "Capsule library instance for DXE_DRIVER module types."
+
diff --git a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleProcessLib.c b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleProcessLib.c
new file mode 100644
index 0000000..13379b2
--- /dev/null
+++ b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleProcessLib.c
@@ -0,0 +1,517 @@
+/** @file
+  DXE capsule process.
+
+  Caution: This module requires additional review when modified.
+  This module will have external input - capsule image.
+  This external input must be validated carefully to avoid security issue like
+  buffer overflow, integer overflow.
+
+  ProcessCapsules(), ProcessTheseCapsules() will receive untrusted
+  input and do basic validation.
+
+  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <PiDxe.h>
+#include <Protocol/EsrtManagement.h>
+
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiLib.h>
+#include <Library/PcdLib.h>
+#include <Library/HobLib.h>
+#include <Library/ReportStatusCodeLib.h>
+#include <Library/CapsuleLib.h>
+
+#include <IndustryStandard/WindowsUxCapsule.h>
+
+/**
+  Return if this FMP is a system FMP or a device FMP, based upon CapsuleHeader.
+
+  @param[in] CapsuleHeader A pointer to EFI_CAPSULE_HEADER
+
+  @retval TRUE  It is a system FMP.
+  @retval FALSE It is a device FMP.
+**/
+BOOLEAN
+IsFmpCapsule(
+  IN EFI_CAPSULE_HEADER *CapsuleHeader
+  );
+
+/**
+  Validate Fmp capsules layout.
+
+  Caution: This function may receive untrusted input.
+
+  This function assumes the caller validated the capsule by using
+  IsValidCapsuleHeader(), so that all fields in EFI_CAPSULE_HEADER are correct.
+  The capsule buffer size is CapsuleHeader->CapsuleImageSize.
+
+  This function validates the fields in EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
+  and EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER.
+
+  This function need support nested FMP capsule.
+
+  @param[in]   CapsuleHeader        Points to a capsule header.
+  @param[out]  IsSystemFmp          If it is a system FMP.
+  @param[out]  EmbeddedDriverCount  The EmbeddedDriverCount in the FMP capsule.
+
+  @retval EFI_SUCESS             Input capsule is a correct FMP capsule.
+  @retval EFI_INVALID_PARAMETER  Input capsule is not a correct FMP capsule.
+**/
+EFI_STATUS
+ValidateFmpCapsule(
+  IN EFI_CAPSULE_HEADER *CapsuleHeader,
+  OUT BOOLEAN           *IsSystemFmp, OPTIONAL
+  OUT UINT16            *EmbeddedDriverCount OPTIONAL
+  );
+
+/**
+  Validate if it is valid capsule header
+
+  This function assumes the caller provided correct CapsuleHeader pointer
+  and CapsuleSize.
+
+  This function validates the fields in EFI_CAPSULE_HEADER.
+
+  @param  CapsuleHeader    Points to a capsule header.
+  @param  CapsuleSize      Size of the whole capsule image.
+
+**/
+BOOLEAN
+IsValidCapsuleHeader(
+  IN EFI_CAPSULE_HEADER  *CapsuleHeader,
+  IN UINT64              CapsuleSize
+  );
+
+extern BOOLEAN                   mDxeCapsuleLibEndOfDxe;
+
+/**
+
+  This routine is called to process capsules.
+
+  Caution: This function may receive untrusted input.
+
+  Each individual capsule result is recorded in capsule record variable.
+  System may reset in this function, if reset is required by capsule.
+
+  @param  IsSystemCapsule         TRUE: This function need process system capsules only.
+                                  FALSE: This function need process non-system capsules only.
+  @param  NeedBlockDriver         TRUE: Need skip the FMP capsules with non zero EmbeddedDriverCount.
+                                  FALSE: No need to skip any FMP capsules.
+
+  @retval EFI_SUCCESS             There is no error when processing capsules.
+  @retval EFI_OUT_OF_RESOURCES    No enough resource to process capsules.
+
+**/
+EFI_STATUS
+ProcessTheseCapsules (
+  IN BOOLEAN  IsSystemCapsule,
+  IN BOOLEAN  NeedBlockDriver
+  )
+{
+  EFI_STATUS                  Status;
+  EFI_PEI_HOB_POINTERS        HobPointer;
+  EFI_CAPSULE_HEADER          *CapsuleHeader;
+  UINT32                      Size;
+  UINT32                      CapsuleNumber;
+  UINT32                      CapsuleTotalNumber;
+  EFI_CAPSULE_TABLE           *CapsuleTable;
+  UINT32                      Index;
+  UINT32                      CacheIndex;
+  UINT32                      CacheNumber;
+  VOID                        **CapsulePtr;
+  VOID                        **CapsulePtrCache;
+  EFI_GUID                    *CapsuleGuidCache;
+  BOOLEAN                     NeedReset;
+  EFI_STATUS                  *CapsuleStatusArray;
+  BOOLEAN                     DisplayCapsuleExist;
+  ESRT_MANAGEMENT_PROTOCOL    *EsrtManagement;
+  BOOLEAN                     IsSystemFmp;
+  UINT16                      EmbeddedDriverCount;
+
+  REPORT_STATUS_CODE(EFI_PROGRESS_CODE, (PcdGet32(PcdStatusCodeSubClassCapsule) | PcdGet32(PcdCapsuleStatusCodeProcessCapsulesBegin)));
+
+  CapsuleNumber       = 0;
+  CapsuleTotalNumber  = 0;
+  CacheIndex          = 0;
+  CacheNumber         = 0;
+  CapsulePtr          = NULL;
+  CapsulePtrCache     = NULL;
+  CapsuleGuidCache    = NULL;
+  NeedReset           = FALSE;
+  DisplayCapsuleExist = FALSE;
+  EsrtManagement      = NULL;
+
+  Status = EFI_SUCCESS;
+  //
+  // 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 {
+      CapsuleTotalNumber++;
+    }
+    HobPointer.Raw = GET_NEXT_HOB (HobPointer);
+  }
+
+  if (CapsuleTotalNumber == 0) {
+    //
+    // We didn't find a hob, so had no errors.
+    //
+    DEBUG ((EFI_D_ERROR, "We can not find capsule data in capsule update boot mode.\n"));
+    Status = EFI_SUCCESS;
+    goto Done;
+  }
+
+  //
+  // Init temp Capsule Data table.
+  //
+  CapsulePtr       = (VOID **) AllocateZeroPool (sizeof (VOID *) * CapsuleTotalNumber);
+  ASSERT (CapsulePtr != NULL);
+  if (CapsulePtr == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto Done;
+  }
+  CapsulePtrCache  = (VOID **) AllocateZeroPool (sizeof (VOID *) * CapsuleTotalNumber);
+  ASSERT (CapsulePtrCache != NULL);
+  if (CapsulePtrCache == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto Done;
+  }
+  CapsuleGuidCache = (EFI_GUID *) AllocateZeroPool (sizeof (EFI_GUID) * CapsuleTotalNumber);
+  ASSERT (CapsuleGuidCache != NULL);
+  if (CapsuleGuidCache == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto Done;
+  }
+  CapsuleStatusArray = (EFI_STATUS *) AllocateZeroPool (sizeof (EFI_STATUS) * CapsuleTotalNumber);
+  ASSERT (CapsuleStatusArray != NULL);
+  if (CapsuleStatusArray == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto Done;
+  }
+
+  //
+  // Find all capsule images from hob
+  //
+  HobPointer.Raw = GetHobList ();
+  while ((HobPointer.Raw = GetNextHob (EFI_HOB_TYPE_UEFI_CAPSULE, HobPointer.Raw)) != NULL) {
+    CapsulePtr [CapsuleNumber++] = (VOID *) (UINTN) HobPointer.Capsule->BaseAddress;
+    HobPointer.Raw = GET_NEXT_HOB (HobPointer);
+  }
+
+  if (!IsSystemCapsule) {
+    //
+    //Check the capsule flags,if contains CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE, install
+    //capsuleTable to configure table with EFI_CAPSULE_GUID
+    //
+
+    //
+    // Capsules who have CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE always are used for operating
+    // System to have information persist across a system reset. EFI System Table must
+    // point to an array of capsules that contains the same CapsuleGuid value. And agents
+    // searching for this type capsule will look in EFI System Table and search for the
+    // capsule's Guid and associated pointer to retrieve the data. Two steps below describes
+    // how to sorting the capsules by the unique guid and install the array to EFI System Table.
+    // Firstly, Loop for all coalesced capsules, record unique CapsuleGuids and cache them in an
+    // array for later sorting capsules by CapsuleGuid.
+    //
+    for (Index = 0; Index < CapsuleTotalNumber; Index++) {
+      CapsuleStatusArray [Index] = EFI_UNSUPPORTED;
+      CapsuleHeader = (EFI_CAPSULE_HEADER*) CapsulePtr [Index];
+      if ((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) != 0) {
+        //
+        // For each capsule, we compare it with known CapsuleGuid in the CacheArray.
+        // If already has the Guid, skip it. Whereas, record it in the CacheArray as
+        // an additional one.
+        //
+        CacheIndex = 0;
+        while (CacheIndex < CacheNumber) {
+          if (CompareGuid(&CapsuleGuidCache[CacheIndex],&CapsuleHeader->CapsuleGuid)) {
+            break;
+          }
+          CacheIndex++;
+        }
+        if (CacheIndex == CacheNumber) {
+          CopyMem(&CapsuleGuidCache[CacheNumber++],&CapsuleHeader->CapsuleGuid,sizeof(EFI_GUID));
+        }
+      }
+    }
+
+    //
+    // Secondly, for each unique CapsuleGuid in CacheArray, gather all coalesced capsules
+    // whose guid is the same as it, and malloc memory for an array which preceding
+    // with UINT32. The array fills with entry point of capsules that have the same
+    // CapsuleGuid, and UINT32 represents the size of the array of capsules. Then install
+    // this array into EFI System Table, so that agents searching for this type capsule
+    // will look in EFI System Table and search for the capsule's Guid and associated
+    // pointer to retrieve the data.
+    //
+    CacheIndex = 0;
+    while (CacheIndex < CacheNumber) {
+      CapsuleNumber = 0;
+      for (Index = 0; Index < CapsuleTotalNumber; Index++) {
+        CapsuleHeader = (EFI_CAPSULE_HEADER*) CapsulePtr [Index];
+        if ((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) != 0) {
+          if (CompareGuid (&CapsuleGuidCache[CacheIndex], &CapsuleHeader->CapsuleGuid)) {
+            //
+            // Cache Caspuleheader to the array, this array is uniqued with certain CapsuleGuid.
+            //
+            CapsulePtrCache[CapsuleNumber++] = (VOID*)CapsuleHeader;
+            //
+            // When a Capsule is listed in CapsulePtrCache, it will be reported in ConfigurationTable
+            // So, report the CapsuleStatus as "processed successfully".
+            //
+            CapsuleStatusArray [Index] = EFI_SUCCESS;
+          }
+        }
+      }
+      if (CapsuleNumber != 0) {
+        Size = sizeof(EFI_CAPSULE_TABLE) + (CapsuleNumber - 1) * sizeof(VOID*);
+        CapsuleTable = AllocateRuntimePool (Size);
+        ASSERT (CapsuleTable != NULL);
+        if (CapsuleTable == NULL) {
+          return EFI_OUT_OF_RESOURCES;
+        }
+        CapsuleTable->CapsuleArrayNumber =  CapsuleNumber;
+        CopyMem(&CapsuleTable->CapsulePtr[0], CapsulePtrCache, CapsuleNumber * sizeof(VOID*));
+        Status = gBS->InstallConfigurationTable (&CapsuleGuidCache[CacheIndex], (VOID*)CapsuleTable);
+        ASSERT_EFI_ERROR (Status);
+      }
+      CacheIndex++;
+    }
+  }
+
+  REPORT_STATUS_CODE(EFI_PROGRESS_CODE, (PcdGet32(PcdStatusCodeSubClassCapsule) | PcdGet32(PcdCapsuleStatusCodeUpdatingFirmware)));
+
+  //
+  // If Windows UX capsule exist, process it first
+  //
+  for (Index = 0; Index < CapsuleTotalNumber; Index++) {
+    CapsuleHeader = (EFI_CAPSULE_HEADER*) CapsulePtr [Index];
+    if (CompareGuid(&CapsuleHeader->CapsuleGuid ,&gWindowsUxCapsuleGuid)) {
+      DEBUG ((EFI_D_INFO, "ProcessCapsuleImage (Ux) - 0x%x\n", CapsuleHeader));
+      DisplayCapsuleExist = TRUE;
+      DEBUG ((DEBUG_INFO, "Display logo capsule is found.\n"));
+      Status = ProcessCapsuleImage (CapsuleHeader);
+      DEBUG((EFI_D_INFO, "ProcessCapsuleImage (Ux) - %r\n", Status));
+      CapsuleStatusArray [Index] = Status;
+      break;
+    }
+  }
+
+  if (!DisplayCapsuleExist) {
+    //
+    // Display Capsule not found. Display the default string.
+    //
+    Print (L"Updating the firmware ......\r\n");
+  }
+
+  //
+  // All capsules left are recognized by platform.
+  //
+  for (Index = 0; Index < CapsuleTotalNumber; Index++) {
+    CapsuleHeader = (EFI_CAPSULE_HEADER*) CapsulePtr [Index];
+    if (!CompareGuid(&CapsuleHeader->CapsuleGuid ,&gWindowsUxCapsuleGuid)) {
+      //
+      // Call capsule library to process capsule image.
+      //
+      IsSystemFmp = FALSE;
+      EmbeddedDriverCount = 0;
+      if (IsFmpCapsule(CapsuleHeader)) {
+        Status = ValidateFmpCapsule(CapsuleHeader, &IsSystemFmp, &EmbeddedDriverCount);
+        if (EFI_ERROR(Status)) {
+          DEBUG((DEBUG_ERROR, "ValidateFmpCapsule failed. Ignore!\n"));
+          continue;
+        }
+      }
+
+      if ((IsSystemFmp == IsSystemCapsule) &&
+          ((!NeedBlockDriver) || (EmbeddedDriverCount == 0)) ) {
+        DEBUG((EFI_D_INFO, "ProcessCapsuleImage - 0x%x\n", CapsuleHeader));
+        Status = ProcessCapsuleImage (CapsuleHeader);
+        CapsuleStatusArray [Index] = Status;
+        DEBUG((EFI_D_INFO, "ProcessCapsuleImage - %r\n", Status));
+
+        if (EFI_ERROR(Status)) {
+          REPORT_STATUS_CODE(EFI_ERROR_CODE, (PcdGet32(PcdStatusCodeSubClassCapsule) | PcdGet32(PcdCapsuleStatusCodeUpdateFirmwareFailed)));
+          DEBUG ((DEBUG_ERROR, "Capsule process failed. reset the system!\n"));
+          Print (L"Firmware update failed...\r\n");
+          NeedReset = TRUE;
+        } else {
+          REPORT_STATUS_CODE(EFI_PROGRESS_CODE, (PcdGet32(PcdStatusCodeSubClassCapsule) | PcdGet32(PcdCapsuleStatusCodeUpdateFirmwareSuccess)));
+        }
+
+        if ((CapsuleHeader->Flags & PcdGet16(PcdSystemRebootAfterCapsuleProcessFlag)) != 0 ||
+            IsFmpCapsule(CapsuleHeader)) {
+          NeedReset = TRUE;
+        }
+      }
+    }
+  }
+
+  Status = gBS->LocateProtocol(&gEsrtManagementProtocolGuid, NULL, (VOID **)&EsrtManagement);
+  //
+  // Always sync ESRT Cache from FMP Instance
+  //
+  if (!EFI_ERROR(Status)) {
+    EsrtManagement->SyncEsrtFmp();
+  }
+  Status = EFI_SUCCESS;
+
+  //
+  // Reboot System if required after all capsule processed
+  //
+  if (NeedReset) {
+    REPORT_STATUS_CODE(EFI_PROGRESS_CODE, (PcdGet32(PcdStatusCodeSubClassCapsule) | PcdGet32(PcdCapsuleStatusCodeProcessCapsulesEnd)));
+    REPORT_STATUS_CODE(EFI_PROGRESS_CODE, (PcdGet32(PcdStatusCodeSubClassCapsule) | PcdGet32(PcdCapsuleStatusCodeResettingSystem)));
+
+    Print(L"Capsule Request Cold Reboot.\n");
+    DEBUG((EFI_D_INFO, "Capsule Request Cold Reboot."));
+
+    for (Index = 5; Index > 0; Index--) {
+      Print(L"\rResetting system in %d seconds ...", Index);
+      DEBUG((EFI_D_INFO, "\rResetting system in %d seconds ...", Index));
+      gBS->Stall (1000000);
+    }
+
+    gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL);
+
+    CpuDeadLoop ();
+  }
+
+Done:
+  //
+  // Free the allocated temp memory space.
+  //
+  if (CapsuleGuidCache != NULL) {
+    FreePool(CapsuleGuidCache);
+  }
+  if (CapsulePtrCache != NULL) {
+    FreePool(CapsulePtrCache);
+  }
+  if (CapsulePtr != NULL) {
+    FreePool(CapsulePtr);
+  }
+
+  REPORT_STATUS_CODE(EFI_PROGRESS_CODE, (PcdGet32(PcdStatusCodeSubClassCapsule) | PcdGet32(PcdCapsuleStatusCodeProcessCapsulesEnd)));
+
+  return Status;
+}
+
+/**
+
+  This routine is called to process system capsules.
+
+  Caution: This function may receive untrusted input.
+
+  The non-system capsules are skipped.
+  Each individual capsule result is recorded in capsule record variable.
+  System may reset in this function, if reset is required by capsule.
+
+  @retval EFI_SUCCESS             There is no error when processing capsules.
+  @retval EFI_OUT_OF_RESOURCES    No enough resource to process capsules.
+
+**/
+EFI_STATUS
+ProcessSystemCapsules(
+  VOID
+  )
+{
+  return ProcessTheseCapsules(TRUE, TRUE);
+}
+
+/**
+
+  This routine is called to process non-system capsules.
+
+  Caution: This function may receive untrusted input.
+
+  The system capsules are skipped.
+  Each individual capsule result is recorded in capsule record variable.
+
+  @param  NeedBlockDriver         TRUE: Need skip the FMP capsules with non zero EmbeddedDriverCount.
+                                  FALSE: No need to skip any FMP capsules.
+
+  @retval EFI_SUCCESS             There is no error when processing capsules.
+  @retval EFI_OUT_OF_RESOURCES    No enough resource to process capsules.
+
+**/
+EFI_STATUS
+ProcessNonSystemCapsules(
+  IN BOOLEAN  NeedBlockDriver
+  )
+{
+  return ProcessTheseCapsules(FALSE, NeedBlockDriver);
+}
+
+/**
+
+  This routine is called to process capsules.
+
+  Caution: This function may receive untrusted input.
+
+  If the current boot mode is NOT BOOT_ON_FLASH_UPDATE, this routine does nothing.
+  If the current boot mode is BOOT_ON_FLASH_UPDATE, the capsules reported in
+  EFI_HOB_UEFI_CAPSULE are processed. If there is no EFI_HOB_UEFI_CAPSULE, this
+  routine does nothing.
+
+  This routine should be called twice in BDS.
+  1) The first call must be before EndOfDxe. The system capsules is processed.
+     If device capsule FMP protocols are exposted at this time and device FMP
+     capsule has zero EmbeddedDriverCount, the device capsules are processed.
+     Each individual capsule result is recorded in capsule record variable.
+     System may reset in this function, if reset is required by capsule.
+
+  2) The second call must be after EndOfDxe and after ConnectAll, so that all
+     device capsule FMP protocols are exposed.
+     The system capsules are skipped. If the device capsules are NOT processed
+     in first call, they are processed here.
+     Each individual capsule result is recorded in capsule record variable.
+     System may reset in this function, if reset is required by capsule.
+
+  @retval EFI_SUCCESS             There is no error when processing capsules.
+  @retval EFI_OUT_OF_RESOURCES    No enough resource to process capsules.
+
+**/
+EFI_STATUS
+EFIAPI
+ProcessCapsules(
+  VOID
+  )
+{
+  EFI_BOOT_MODE                 BootMode;
+  EFI_STATUS                    Status;
+  EFI_STATUS                    StatusRet;
+
+  BootMode = GetBootModeHob();
+  if (BootMode != BOOT_ON_FLASH_UPDATE) {
+    return EFI_SUCCESS;
+  }
+
+  if (!mDxeCapsuleLibEndOfDxe) {
+    Status = ProcessSystemCapsules();
+    StatusRet = ProcessNonSystemCapsules(TRUE);
+    if (EFI_ERROR(StatusRet)) {
+      StatusRet = Status;
+    }
+  } else {
+    StatusRet = ProcessNonSystemCapsules(FALSE);
+  }
+  return StatusRet;
+}
diff --git a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleReportLib.c b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleReportLib.c
new file mode 100644
index 0000000..2f8f141
--- /dev/null
+++ b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleReportLib.c
@@ -0,0 +1,447 @@
+/** @file
+  DXE capsule report related function.
+
+  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <PiDxe.h>
+#include <Protocol/FirmwareManagement.h>
+#include <Protocol/VariableLock.h>
+#include <Guid/CapsuleReport.h>
+#include <Guid/FmpCapsule.h>
+#include <Guid/CapsuleVendor.h>
+
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiLib.h>
+#include <Library/PcdLib.h>
+#include <Library/HobLib.h>
+#include <Library/PrintLib.h>
+#include <Library/ReportStatusCodeLib.h>
+#include <Library/CapsuleLib.h>
+
+#include <IndustryStandard/WindowsUxCapsule.h>
+
+/**
+  Get current capsule last variable index.
+
+  @return Current capsule last variable index.
+  @retval -1  No current capsule last variable.
+**/
+INTN
+GetCurrentCapsuleLastIndex(
+  VOID
+  )
+{
+  UINTN                            Size;
+  CHAR16                           CapsuleLastStr[sizeof("Capsule####")];
+  EFI_STATUS                       Status;
+  UINT16                           CurrentIndex;
+
+  Size = sizeof(L"Capsule####") - sizeof(CHAR16); // no zero terminator
+  Status = gRT->GetVariable(
+                  L"CapsuleLast",
+                  &gEfiCapsuleReportGuid,
+                  NULL,
+                  &Size,
+                  CapsuleLastStr
+                  );
+  if (EFI_ERROR(Status)) {
+    return -1;
+  }
+  CurrentIndex = (UINT16)StrHexToUintn(&CapsuleLastStr[sizeof("Capsule") - 1]);
+  return CurrentIndex;
+}
+
+/**
+  Check if this FMP capsule is recorded.
+
+  @param CapsuleHeader  The capsule image header
+  @param PayloadIndex   FMP payload index
+  @param ImageHeader    FMP image header
+
+  @retval TRUE  This FMP capsule is recorded.
+  @retval FALSE This FMP capsule is not recorded.
+**/
+BOOLEAN
+IsFmpCapsuleVariableRecorded(
+  IN EFI_CAPSULE_HEADER                           *CapsuleHeader,
+  IN UINTN                                        PayloadIndex,
+  IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader
+  )
+{
+  EFI_STATUS                          Status;
+  UINT16                              Index;
+  INTN                                CurrentIndex;
+  CHAR16                              CapsuleVarName[20];
+  CHAR16                              *TempVarName;
+  EFI_CAPSULE_RESULT_VARIABLE_HEADER  *CapsuleResult;
+  EFI_CAPSULE_RESULT_VARIABLE_FMP     *CapsuleResultFmp;
+
+  CurrentIndex = GetCurrentCapsuleLastIndex();
+  if (CurrentIndex == -1) {
+    return FALSE;
+  }
+
+  StrCpyS(CapsuleVarName, sizeof(CapsuleVarName) / sizeof(CapsuleVarName[0]), L"Capsule");
+  TempVarName = CapsuleVarName + StrLen(CapsuleVarName);
+  for (Index = 0; Index < (UINT16)CurrentIndex; Index++) {
+    UnicodeSPrint(TempVarName, 5 * sizeof(CHAR16), L"%04x", Index);
+    Status = GetVariable2 (
+               CapsuleVarName,
+               &gEfiCapsuleReportGuid,
+               (VOID **) &CapsuleResult,
+               NULL
+               );
+    if (Status == EFI_NOT_FOUND) {
+      break;
+    } else if (EFI_ERROR(Status)) {
+      continue;
+    }
+    //
+    // Check
+    //
+    if (CapsuleResult->VariableTotalSize >= sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER)) {
+      if (CompareGuid(&CapsuleResult->CapsuleGuid, &gEfiFmpCapsuleGuid)) {
+        if (CapsuleResult->VariableTotalSize >= sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER) + sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP)) {
+          CapsuleResultFmp = (EFI_CAPSULE_RESULT_VARIABLE_FMP *)(CapsuleResult + 1);
+          if (CompareGuid(&CapsuleResultFmp->UpdateImageTypeId, &ImageHeader->UpdateImageTypeId) &&
+              (CapsuleResultFmp->UpdateImageIndex == ImageHeader->UpdateImageIndex) &&
+              (CapsuleResultFmp->PayloadIndex == PayloadIndex) ) {
+            return TRUE;
+          }
+        }
+      }
+    }
+  }
+
+  return FALSE;
+}
+
+/**
+  Get a new capsule status variable index.
+
+  @return A new capsule status variable index.
+  @retval -1  No new capsule status variable index.
+**/
+INTN
+GetNewCapsuleResultIndex(
+  VOID
+  )
+{
+  INTN                             CurrentIndex;
+
+  CurrentIndex = GetCurrentCapsuleLastIndex();
+  if (CurrentIndex >= PcdGet16(PcdCapsuleMax)) {
+    return -1;
+  }
+
+  return CurrentIndex + 1;
+}
+
+/**
+  Write a new capsule status variable.
+
+  @param CapsuleResult      The capsule status variable
+  @param CapsuleResultSize  The size of the capsule stauts variable in bytes
+
+  @retval EFI_SUCCESS          The capsule status variable is recorded.
+  @retval EFI_OUT_OF_RESOURCES No resource to record the capsule status variable.
+**/
+EFI_STATUS
+WriteNewCapsuleResultVariable(
+  IN VOID    *CapsuleResult,
+  IN UINTN   CapsuleResultSize
+  )
+{
+  INTN                                CapsuleResultIndex;
+  CHAR16                              CapsuleResultStr[sizeof("Capsule####")];
+  UINTN                               Size;
+  EFI_STATUS                          Status;
+
+  CapsuleResultIndex = GetNewCapsuleResultIndex();
+  DEBUG((EFI_D_INFO, "New CapsuleResultIndex - 0x%x\n", CapsuleResultIndex));
+  if (CapsuleResultIndex == -1) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+  UnicodeSPrint(
+    CapsuleResultStr,
+    sizeof(CapsuleResultStr),
+    L"Capsule%04x",
+    CapsuleResultIndex
+    );
+
+  Status = gRT->SetVariable(
+                  CapsuleResultStr,
+                  &gEfiCapsuleReportGuid,
+                  EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+                  CapsuleResultSize,
+                  CapsuleResult
+                  );
+  if (!EFI_ERROR(Status)) {
+    Size = sizeof(L"Capsule####") - sizeof(CHAR16); // no zero terminator
+    DEBUG((EFI_D_INFO, "Set CapsuleLast - %s\n", CapsuleResultStr));
+    Status = gRT->SetVariable(
+                    L"CapsuleLast",
+                    &gEfiCapsuleReportGuid,
+                    EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+                    Size,
+                    CapsuleResultStr
+                    );
+  }
+
+  return Status;
+}
+
+/**
+  Record capsule status variable.
+
+  @param CapsuleHeader  The capsule image header
+  @param CapsuleStatus  The capsule process stauts
+
+  @retval EFI_SUCCESS          The capsule status variable is recorded.
+  @retval EFI_OUT_OF_RESOURCES No resource to record the capsule status variable.
+**/
+EFI_STATUS
+RecordCapsuleStatusVariable(
+  IN EFI_CAPSULE_HEADER                           *CapsuleHeader,
+  IN EFI_STATUS                                   CapsuleStatus
+  )
+{
+  EFI_CAPSULE_RESULT_VARIABLE_HEADER  CapsuleResultVariable;
+
+  if ((CapsuleHeader->Flags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET) == 0) {
+    return EFI_UNSUPPORTED;
+  }
+
+  CapsuleResultVariable.VariableTotalSize = sizeof(CapsuleResultVariable);
+  CopyGuid (&CapsuleResultVariable.CapsuleGuid, &CapsuleHeader->CapsuleGuid);
+  ZeroMem(&CapsuleResultVariable.CapsuleProcessed, sizeof(CapsuleResultVariable.CapsuleProcessed));
+  gRT->GetTime(&CapsuleResultVariable.CapsuleProcessed, NULL);
+  CapsuleResultVariable.CapsuleStatus = CapsuleStatus;
+
+  return WriteNewCapsuleResultVariable(&CapsuleResultVariable, sizeof(CapsuleResultVariable));
+}
+
+/**
+  Record FMP capsule status variable.
+
+  @param CapsuleHeader  The capsule image header
+  @param CapsuleStatus  The capsule process stauts
+  @param PayloadIndex   FMP payload index
+  @param ImageHeader    FMP image header
+
+  @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
+  )
+{
+  UINT8                               CapsuleResultVariable[sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER) + sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP)];
+  EFI_CAPSULE_RESULT_VARIABLE_HEADER  *CapsuleResultVariableHeader;
+  EFI_CAPSULE_RESULT_VARIABLE_FMP     *CapsuleResultVariableFmp;
+
+  if ((CapsuleHeader->Flags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET) == 0) {
+    return EFI_UNSUPPORTED;
+  }
+
+  CapsuleResultVariableHeader = (VOID *)&CapsuleResultVariable[0];
+  CapsuleResultVariableHeader->VariableTotalSize = sizeof(CapsuleResultVariable);
+  CopyGuid(&CapsuleResultVariableHeader->CapsuleGuid, &CapsuleHeader->CapsuleGuid);
+  ZeroMem(&CapsuleResultVariableHeader->CapsuleProcessed, sizeof(CapsuleResultVariableHeader->CapsuleProcessed));
+  gRT->GetTime(&CapsuleResultVariableHeader->CapsuleProcessed, NULL);
+  CapsuleResultVariableHeader->CapsuleStatus = CapsuleStatus;
+
+  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);
+
+  return WriteNewCapsuleResultVariable(&CapsuleResultVariable, sizeof(CapsuleResultVariable));
+}
+
+/**
+  Initialize CapsuleMax variables.
+**/
+VOID
+InitCapsuleMaxVariable(
+  VOID
+  )
+{
+  EFI_STATUS                       Status;
+  UINTN                            Size;
+  CHAR16                           CapsuleMaxStr[sizeof("Capsule####")];
+  EDKII_VARIABLE_LOCK_PROTOCOL     *VariableLock;
+
+  UnicodeSPrint(
+    CapsuleMaxStr,
+    sizeof(CapsuleMaxStr),
+    L"Capsule%04x",
+    PcdGet16(PcdCapsuleMax)
+    );
+
+  Size = sizeof(L"Capsule####") - sizeof(CHAR16); // no zero terminator
+  Status = gRT->SetVariable(
+                  L"CapsuleMax",
+                  &gEfiCapsuleReportGuid,
+                  EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+                  Size,
+                  CapsuleMaxStr
+                  );
+  if (!EFI_ERROR(Status)) {
+    // Lock it per UEFI spec.
+    Status = gBS->LocateProtocol(&gEdkiiVariableLockProtocolGuid, NULL, (VOID **)&VariableLock);
+    if (!EFI_ERROR(Status)) {
+      Status = VariableLock->RequestToLock(VariableLock, L"CapsuleMax", &gEfiCapsuleReportGuid);
+      ASSERT_EFI_ERROR(Status);
+    }
+  }
+}
+
+/**
+  Initialize CapsuleLast variables.
+**/
+VOID
+InitCapsuleLastVariable(
+  VOID
+  )
+{
+  EFI_STATUS                       Status;
+  EFI_BOOT_MODE                    BootMode;
+  EDKII_VARIABLE_LOCK_PROTOCOL     *VariableLock;
+  VOID                             *CapsuleResult;
+  UINTN                            Size;
+  CHAR16                           CapsuleLastStr[sizeof("Capsule####")];
+
+  BootMode = GetBootModeHob();
+  if (BootMode == BOOT_ON_FLASH_UPDATE) {
+    Status = gRT->SetVariable(
+                    L"CapsuleLast",
+                    &gEfiCapsuleReportGuid,
+                    EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+                    0,
+                    NULL
+                    );
+    // Do not lock it because it will be updated later.
+  } else {
+    //
+    // Check if OS/APP cleared L"Capsule####"
+    //
+    ZeroMem(CapsuleLastStr, sizeof(CapsuleLastStr));
+    Size = sizeof(L"Capsule####") - sizeof(CHAR16); // no zero terminator
+    Status = gRT->GetVariable(
+                    L"CapsuleLast",
+                    &gEfiCapsuleReportGuid,
+                    NULL,
+                    &Size,
+                    CapsuleLastStr
+                    );
+    if (!EFI_ERROR(Status)) {
+      //
+      // L"CapsuleLast" is got, check if data is there.
+      //
+      Status = GetVariable2 (
+                 CapsuleLastStr,
+                 &gEfiCapsuleReportGuid,
+                 (VOID **) &CapsuleResult,
+                 NULL
+                 );
+      if (EFI_ERROR(Status)) {
+        //
+        // If no data, delete L"CapsuleLast"
+        //
+        Status = gRT->SetVariable(
+                        L"CapsuleLast",
+                        &gEfiCapsuleReportGuid,
+                        EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+                        0,
+                        NULL
+                        );
+      }
+    }
+
+    // Lock it in normal boot path per UEFI spec.
+    Status = gBS->LocateProtocol(&gEdkiiVariableLockProtocolGuid, NULL, (VOID **)&VariableLock);
+    if (!EFI_ERROR(Status)) {
+      Status = VariableLock->RequestToLock(VariableLock, L"CapsuleLast", &gEfiCapsuleReportGuid);
+      ASSERT_EFI_ERROR(Status);
+    }
+  }
+}
+
+/**
+  Initialize capsule update variables.
+**/
+VOID
+InitCapsuleUpdateVariable(
+  VOID
+  )
+{
+  EFI_STATUS                     Status;
+  UINTN                          Index;
+  CHAR16                         CapsuleVarName[30];
+  CHAR16                         *TempVarName;
+
+  //
+  // Clear all the capsule variables CapsuleUpdateData, CapsuleUpdateData1, CapsuleUpdateData2...
+  // as early as possible which will avoid the next time boot after the capsule update
+  // will still into the capsule loop
+  //
+  StrCpyS (CapsuleVarName, sizeof(CapsuleVarName)/sizeof(CapsuleVarName[0]), EFI_CAPSULE_VARIABLE_NAME);
+  TempVarName = CapsuleVarName + StrLen (CapsuleVarName);
+  Index = 0;
+  while (TRUE) {
+    if (Index > 0) {
+      UnicodeValueToString (TempVarName, 0, Index, 0);
+    }
+    Status = gRT->SetVariable (
+                    CapsuleVarName,
+                    &gEfiCapsuleVendorGuid,
+                    EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS,
+                    0,
+                    (VOID *)NULL
+                    );
+    if (EFI_ERROR (Status)) {
+      //
+      // There is no capsule variables, quit
+      //
+      break;
+    }
+    Index++;
+  }
+}
+
+/**
+  Initialize capsule related variables.
+**/
+VOID
+InitCapsuleVariable(
+  VOID
+  )
+{
+  InitCapsuleUpdateVariable();
+  InitCapsuleMaxVariable();
+  InitCapsuleLastVariable();
+  //
+  // 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/DxeCapsuleRuntime.c b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleRuntime.c
new file mode 100644
index 0000000..8801439
--- /dev/null
+++ b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleRuntime.c
@@ -0,0 +1,112 @@
+/** @file
+  Capsule library runtime support.
+
+  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <PiDxe.h>
+
+#include <Guid/FmpCapsule.h>
+#include <Guid/SystemResourceTable.h>
+#include <Guid/EventGroup.h>
+
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/MemoryAllocationLib.h>
+
+extern EFI_SYSTEM_RESOURCE_TABLE *mEsrtTable;
+extern BOOLEAN                   mIsVirtualAddrConverted;
+
+/**
+  Convert EsrtTable physical address to virtual address.
+
+  @param[in] Event      Event whose notification function is being invoked.
+  @param[in] Context    The pointer to the notification function's context, which
+                        is implementation-dependent.
+**/
+VOID
+EFIAPI
+DxeCapsuleLibVirtualAddressChangeEvent (
+  IN  EFI_EVENT   Event,
+  IN  VOID        *Context
+  )
+{
+  UINTN                    Index;
+  EFI_CONFIGURATION_TABLE  *ConfigEntry;
+
+  //
+  // Get Esrt table first
+  //
+  ConfigEntry = gST->ConfigurationTable;
+  for (Index = 0; Index < gST->NumberOfTableEntries; Index++) {
+    if (CompareGuid(&gEfiSystemResourceTableGuid, &ConfigEntry->VendorGuid)) {
+      break;
+    }
+    ConfigEntry++;
+  }
+
+  //
+  // If no Esrt table installed in Configure Table
+  //
+  if (Index < gST->NumberOfTableEntries) {
+    //
+    // Search Esrt to check given capsule is qualified
+    //
+    mEsrtTable = (EFI_SYSTEM_RESOURCE_TABLE *) ConfigEntry->VendorTable;
+
+    //
+    // Update protocol pointer to Esrt Table.
+    //
+    gRT->ConvertPointer (0x00, (VOID**) &(mEsrtTable));
+  }
+
+  mIsVirtualAddrConverted = TRUE;
+
+}
+
+/**
+  The constructor function hook VirtualAddressChange event to use ESRT table as capsule routing table.
+
+  @param  ImageHandle   The firmware allocated handle for the EFI image.
+  @param  SystemTable   A pointer to the EFI System Table.
+
+  @retval EFI_SUCCESS   The constructor successfully .
+**/
+EFI_STATUS
+EFIAPI
+DxeRuntimeCapsuleLibConstructor (
+  IN EFI_HANDLE         ImageHandle,
+  IN EFI_SYSTEM_TABLE   *SystemTable
+  )
+{
+  EFI_STATUS     Status;
+  EFI_EVENT      Event;
+
+  //
+  // Make sure we can handle virtual address changes.
+  //
+  Event = NULL;
+  Status = gBS->CreateEventEx (
+                  EVT_NOTIFY_SIGNAL,
+                  TPL_NOTIFY,
+                  DxeCapsuleLibVirtualAddressChangeEvent,
+                  NULL,
+                  &gEfiEventVirtualAddressChangeGuid,
+                  &Event
+                  );
+  ASSERT_EFI_ERROR (Status);
+
+  return EFI_SUCCESS;
+}
diff --git a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf
new file mode 100644
index 0000000..2eed206
--- /dev/null
+++ b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf
@@ -0,0 +1,85 @@
+## @file
+#  Capsule library instance for DXE_RUNTIME_DRIVER.
+#
+#  Capsule library instance for DXE_RUNTIME_DRIVER module types.
+#
+#  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = DxeRuntimeCapsuleLib
+  MODULE_UNI_FILE                = DxeRuntimeCapsuleLib.uni
+  FILE_GUID                      = 19BE1E4B-1A9A-44c1-8F12-32DD0470516A
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = CapsuleLib|DXE_RUNTIME_DRIVER
+  CONSTRUCTOR                    = DxeCapsuleLibConstructor
+  CONSTRUCTOR                    = DxeRuntimeCapsuleLibConstructor
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64 IPF EBC
+#
+
+[Sources]
+  DxeCapsuleLib.c
+  DxeCapsuleProcessLib.c
+  DxeCapsuleReportLib.c
+  DxeCapsuleRuntime.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+  BaseLib
+  BaseMemoryLib
+  DebugLib
+  MemoryAllocationLib
+  DxeServicesTableLib
+  UefiBootServicesTableLib
+  DevicePathLib
+  ReportStatusCodeLib
+  PrintLib
+  HobLib
+  EdkiiSystemCapsuleLib
+
+[Pcd]
+  gEfiMdeModulePkgTokenSpaceGuid.PcdEdkiiSystemFmpCapsuleImageTypeIdGuid  ## CONSUMES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleMax
+  gEfiMdeModulePkgTokenSpaceGuid.PcdSystemRebootAfterCapsuleProcessFlag
+
+  gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeSubClassCapsule
+  gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleStatusCodeProcessCapsulesBegin
+  gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleStatusCodeProcessCapsulesEnd
+  gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleStatusCodeUpdatingFirmware
+  gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleStatusCodeUpdateFirmwareSuccess
+  gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleStatusCodeUpdateFirmwareFailed
+  gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleStatusCodeResettingSystem
+
+[Protocols]
+  gEsrtManagementProtocolGuid             ## CONSUMES
+  gEfiFirmwareManagementProtocolGuid      ## SOMETIMES_CONSUMES
+  gEdkiiVariableLockProtocolGuid          ## SOMETIMES_CONSUMES
+
+[Guids]
+  gEfiFmpCapsuleGuid                      ## SOMETIMES_CONSUMES ## GUID
+  gWindowsUxCapsuleGuid                   ## SOMETIMES_CONSUMES ## GUID
+  gEfiSystemResourceTableGuid             ## SOMETIMES_CONSUMES ## GUID
+  gEfiCapsuleReportGuid                   ## CONSUMES ## Variable
+  gEfiCapsuleVendorGuid                   ## CONSUMES ## Variable
+  gEfiEndOfDxeEventGroupGuid              ## CONSUMES ## Event
+  gEfiEventVirtualAddressChangeGuid       ## CONSUMES ## Event
+
+[Depex]
+  gEfiVariableWriteArchProtocolGuid
diff --git a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.uni b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.uni
new file mode 100644
index 0000000..cd89b13
--- /dev/null
+++ b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.uni
@@ -0,0 +1,22 @@
+// /** @file
+// Capsule library instance for DXE_RUNTIME_DRIVER.
+//
+// Capsule library instance for DXE_RUNTIME_DRIVER module types.
+//
+// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+//
+// This program and the accompanying materials
+// are licensed and made available under the terms and conditions of the BSD License
+// which accompanies this distribution.  The full text of the license may be found at
+// http://opensource.org/licenses/bsd-license.php
+//
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT             #language en-US "Capsule Support Library"
+
+#string STR_MODULE_DESCRIPTION          #language en-US "Capsule library instance for DXE_RUNTIME_DRIVER module types."
+
-- 
2.7.4.windows.1



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

* [PATCH 11/45] MdeModulePkg/DxeCapsuleLibNull: Add ProcessCapsules() interface.
  2016-09-21  6:44 [PATCH 00/45] Add capsule update and recovery sample Jiewen Yao
                   ` (9 preceding siblings ...)
  2016-09-21  6:44 ` [PATCH 10/45] MdeModulePkg/DxeCapsuleLibFmp: Add DxeCapsuleLibFmp instance Jiewen Yao
@ 2016-09-21  6:44 ` Jiewen Yao
  2016-09-21  6:44 ` [PATCH 12/45] MdeModulePkg/EdkiiSystemCapsuleLib: Add EdkiiSystemCapsuleLib instance Jiewen Yao
                   ` (37 subsequent siblings)
  48 siblings, 0 replies; 83+ messages in thread
From: Jiewen Yao @ 2016-09-21  6:44 UTC (permalink / raw)
  To: edk2-devel; +Cc: Feng Tian, Star Zeng, Michael D Kinney, Liming Gao, Chao Zhang

Add ProcessCapsules() interface for DxeCapsuleLibNull.

Cc: Feng Tian <feng.tian@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Chao Zhang <chao.b.zhang@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
---
 MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.c | 47 ++++++++++++++++++--
 1 file changed, 44 insertions(+), 3 deletions(-)

diff --git a/MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.c b/MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.c
index fb5c255..0f70e4f 100644
--- a/MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.c
+++ b/MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.c
@@ -1,7 +1,7 @@
 /** @file
   Null Dxe Capsule Library instance does nothing and returns unsupport status.
 
-Copyright (c) 2007 - 2008, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2007 - 2016, Intel Corporation. All rights reserved.<BR>
 This program and the accompanying materials
 are licensed and made available under the terms and conditions of the BSD License
 which accompanies this distribution.  The full text of the license may be found at
@@ -17,7 +17,9 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 /**
   The firmware checks whether the capsule image is supported 
   by the CapsuleGuid in CapsuleHeader or other specific information in capsule image.
-  
+
+  Caution: This function may receive untrusted input.
+
   @param  CapsuleHeader    Point to the UEFI capsule image to be checked.
   
   @retval EFI_UNSUPPORTED  Input capsule is not supported by the firmware.
@@ -34,7 +36,9 @@ SupportCapsuleImage (
 /**
   The firmware specific implementation processes the capsule image
   if it recognized the format of this capsule image.
-  
+
+  Caution: This function may receive untrusted input.
+
   @param  CapsuleHeader    Point to the UEFI capsule image to be processed. 
    
   @retval EFI_UNSUPPORTED  Capsule image is not supported by the firmware.
@@ -48,4 +52,41 @@ ProcessCapsuleImage (
   return EFI_UNSUPPORTED;
 }
 
+/**
+
+  This routine is called to process capsules.
+
+  Caution: This function may receive untrusted input.
+
+  If the current boot mode is NOT BOOT_ON_FLASH_UPDATE, this routine does nothing.
+  If the current boot mode is BOOT_ON_FLASH_UPDATE, the capsules reported in
+  EFI_HOB_UEFI_CAPSULE are processed. If there is no EFI_HOB_UEFI_CAPSULE, this
+  routine does nothing.
+
+  This routine should be called twice in BDS.
+  1) The first call must be before EndOfDxe. The system capsules is processed.
+     If device capsule FMP protocols are exposted at this time and device FMP
+     capsule has zero EmbeddedDriverCount, the device capsules are processed.
+     Each individual capsule result is recorded in capsule record variable.
+     System may reset in this function, if reset is required by capsule.
+
+  2) The second call must be after EndOfDxe and after ConnectAll, so that all
+     device capsule FMP protocols are exposed.
+     The system capsules are skipped. If the device capsules are NOT processed
+     in first call, they are processed here.
+     Each individual capsule result is recorded in capsule record variable.
+     System may reset in this function, if reset is required by capsule.
+
+  @retval EFI_SUCCESS             There is no error when processing capsules.
+  @retval EFI_OUT_OF_RESOURCES    No enough resource to process capsules.
+
+**/
+EFI_STATUS
+EFIAPI
+ProcessCapsules(
+  VOID
+  )
+{
+  return EFI_UNSUPPORTED;
+}
 
-- 
2.7.4.windows.1



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

* [PATCH 12/45] MdeModulePkg/EdkiiSystemCapsuleLib: Add EdkiiSystemCapsuleLib instance.
  2016-09-21  6:44 [PATCH 00/45] Add capsule update and recovery sample Jiewen Yao
                   ` (10 preceding siblings ...)
  2016-09-21  6:44 ` [PATCH 11/45] MdeModulePkg/DxeCapsuleLibNull: Add ProcessCapsules() interface Jiewen Yao
@ 2016-09-21  6:44 ` Jiewen Yao
  2016-09-21  6:44 ` [PATCH 13/45] MdeModulePkg/PlatformFlashAccessLib: Add NULL PlatformFlashAccessLib Jiewen Yao
                   ` (36 subsequent siblings)
  48 siblings, 0 replies; 83+ messages in thread
From: Jiewen Yao @ 2016-09-21  6:44 UTC (permalink / raw)
  To: edk2-devel; +Cc: Feng Tian, Star Zeng, Michael D Kinney, Liming Gao, Chao Zhang

This library is used to abstract the action for EDKII system FMP capsule,
such as extracting a component from capsule, or authenticate the capsule.

Cc: Feng Tian <feng.tian@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Chao Zhang <chao.b.zhang@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
---
 MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.c   | 609 ++++++++++++++++++++
 MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.inf |  55 ++
 MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.uni |  22 +
 3 files changed, 686 insertions(+)

diff --git a/MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.c b/MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.c
new file mode 100644
index 0000000..e1bc0b6
--- /dev/null
+++ b/MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.c
@@ -0,0 +1,609 @@
+/** @file
+  EDKII System Capsule library.
+
+  EDKII System Capsule library instance.
+
+  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <PiDxe.h>
+
+#include <Guid/SystemResourceTable.h>
+#include <Guid/FirmwareContentsSigned.h>
+#include <Guid/WinCertificate.h>
+#include <Guid/EdkiiSystemFmpCapsule.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/EdkiiSystemCapsuleLib.h>
+#include <Library/FmpAuthenticationLib.h>
+
+#include <Protocol/FirmwareManagement.h>
+
+EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR   *mImageFmpInfo;
+UINTN                                    mImageFmpInfoSize;
+EFI_GUID                                 mEdkiiSystemFirmwareFileGuid;
+
+/**
+  Check if a block of buffer is erased.
+
+  @param[in] ErasePolarity  Erase polarity attribute of the firmware volume
+  @param[in] InBuffer       The buffer to be checked
+  @param[in] BufferSize     Size of the buffer in bytes
+
+  @retval    TRUE           The block of buffer is erased
+  @retval    FALSE          The block of buffer is not erased
+**/
+BOOLEAN
+IsBufferErased (
+  IN UINT8    ErasePolarity,
+  IN VOID     *InBuffer,
+  IN UINTN    BufferSize
+  )
+{
+  UINTN   Count;
+  UINT8   EraseByte;
+  UINT8   *Buffer;
+
+  if(ErasePolarity == 1) {
+    EraseByte = 0xFF;
+  } else {
+    EraseByte = 0;
+  }
+
+  Buffer = InBuffer;
+  for (Count = 0; Count < BufferSize; Count++) {
+    if (Buffer[Count] != EraseByte) {
+      return FALSE;
+    }
+  }
+
+  return TRUE;
+}
+
+/**
+  Get Section buffer pointer by SectionType and SectionInstance.
+
+  @param[in]   SectionBuffer     The buffer of section
+  @param[in]   SectionBufferSize The size of SectionBuffer in bytes
+  @param[in]   SectionType       The SectionType of Section to be found
+  @param[in]   SectionInstance   The Instance of Section to be found
+  @param[out]  OutSectionBuffer  The section found, including SECTION_HEADER
+  @param[out]  OutSectionSize    The size of section found, including SECTION_HEADER
+
+  @retval TRUE  The FFS buffer is found.
+  @retval FALSE The FFS buffer is not found.
+**/
+BOOLEAN
+GetSectionByType(
+  IN VOID                  *SectionBuffer,
+  IN UINT32                SectionBufferSize,
+  IN EFI_SECTION_TYPE      SectionType,
+  IN UINTN                 SectionInstance,
+  OUT VOID                 **OutSectionBuffer,
+  OUT UINTN                *OutSectionSize
+  )
+{
+  EFI_COMMON_SECTION_HEADER             *SectionHeader;
+  UINTN                                 SectionSize;
+  UINTN                                 Instance;
+
+  DEBUG ((DEBUG_INFO, "GetSectionByType - Buffer: 0x%08x - 0x%08x\n", SectionBuffer, SectionBufferSize));
+
+  //
+  // Find Section
+  //
+  SectionHeader = SectionBuffer;
+
+  Instance = 0;
+  while ((UINTN)SectionHeader < (UINTN)SectionBuffer + SectionBufferSize) {
+    DEBUG ((DEBUG_INFO, "GetSectionByType - Section: 0x%08x\n", SectionHeader));
+    if (IS_SECTION2(SectionHeader)) {
+      SectionSize = SECTION2_SIZE(SectionHeader);
+    } else {
+      SectionSize = SECTION_SIZE(SectionHeader);
+    }
+
+    if (SectionHeader->Type == SectionType) {
+      if (Instance == SectionInstance) {
+        *OutSectionBuffer = (UINT8 *)SectionHeader;
+        *OutSectionSize = SectionSize;
+        DEBUG((DEBUG_INFO, "GetSectionByType - 0x%x - 0x%x\n", *OutSectionBuffer, *OutSectionSize));
+        return TRUE;
+      } else {
+        DEBUG((DEBUG_INFO, "GetSectionByType - find section instance %x\n", Instance));
+        Instance++;
+      }
+    } else {
+      //
+      // Skip other section type
+      //
+      DEBUG ((DEBUG_INFO, "GetSectionByType - other section type 0x%x\n", SectionHeader->Type));
+    }
+
+    //
+    // Next Section
+    //
+    SectionHeader = (EFI_COMMON_SECTION_HEADER *)((UINTN)SectionHeader + ALIGN_VALUE(SectionSize, 4));
+  }
+
+  return FALSE;
+}
+
+/**
+  Get FFS buffer pointer by FileName GUID and FileType.
+
+  @param[in]   FdStart          The BIOS FD image
+  @param[in]   FdSize           The size of BIOS FD image
+  @param[in]   FileName         The FileName GUID of FFS to be found
+  @param[in]   Type             The FileType of FFS to be found
+  @param[out]  OutFfsBuffer     The FFS buffer found, including FFS_FILE_HEADER
+  @param[out]  OutFfsBufferSize The size of FFS buffer found, including FFS_FILE_HEADER
+
+  @retval TRUE  The FFS buffer is found.
+  @retval FALSE The FFS buffer is not found.
+**/
+BOOLEAN
+GetFfsByName (
+  IN VOID                  *FdStart,
+  IN UINTN                 FdSize,
+  IN EFI_GUID              *FileName,
+  IN EFI_FV_FILETYPE       Type,
+  OUT VOID                 **OutFfsBuffer,
+  OUT UINTN                *OutFfsBufferSize
+  )
+{
+  UINTN                                     FvSize;
+  EFI_FIRMWARE_VOLUME_HEADER                *FvHeader;
+  EFI_FIRMWARE_VOLUME_EXT_HEADER            *FvExtHeader;
+  EFI_FFS_FILE_HEADER                       *FfsHeader;
+  UINT32                                    FfsSize;
+  UINTN                                     TestLength;
+  BOOLEAN                                   FvFound;
+
+  DEBUG ((DEBUG_INFO, "GetFfsByName - FV: 0x%08x - 0x%08x\n", (UINTN)FdStart, (UINTN)FdSize));
+
+  FvFound = FALSE;
+  FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)FdStart;
+  while ((UINTN)FvHeader < (UINTN)FdStart + FdSize - 1) {
+    FvSize = (UINTN)FdStart + FdSize - (UINTN)FvHeader;
+
+    if (FvHeader->Signature != EFI_FVH_SIGNATURE) {
+      FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)((UINTN)FvHeader + SIZE_4KB);
+      continue;
+    }
+    DEBUG((DEBUG_ERROR, "checking FV....0x%08x - 0x%x\n", FvHeader, FvHeader->FvLength));
+    FvFound = TRUE;
+    if (FvHeader->FvLength > FvSize) {
+      DEBUG((DEBUG_ERROR, "GetFfsByName - FvSize: 0x%08x, MaxSize - 0x%08x\n", (UINTN)FvHeader->FvLength, (UINTN)FvSize));
+      return FALSE;
+    }
+    FvSize = (UINTN)FvHeader->FvLength;
+
+    //
+    // Find FFS
+    //
+    if (FvHeader->ExtHeaderOffset != 0) {
+      FvExtHeader = (EFI_FIRMWARE_VOLUME_EXT_HEADER *)((UINT8 *)FvHeader + FvHeader->ExtHeaderOffset);
+      FfsHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FvExtHeader + FvExtHeader->ExtHeaderSize);
+    } else {
+      FfsHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FvHeader + FvHeader->HeaderLength);
+    }
+    FfsHeader = (EFI_FFS_FILE_HEADER *)((UINTN)FvHeader + ALIGN_VALUE((UINTN)FfsHeader - (UINTN)FvHeader, 8));
+
+    while ((UINTN)FfsHeader < (UINTN)FvHeader + FvSize - 1) {
+      DEBUG((DEBUG_INFO, "GetFfsByName - FFS: 0x%08x\n", FfsHeader));
+      TestLength = (UINTN)((UINTN)FvHeader + FvSize - (UINTN)FfsHeader);
+      if (TestLength > sizeof(EFI_FFS_FILE_HEADER)) {
+        TestLength = sizeof(EFI_FFS_FILE_HEADER);
+      }
+      if (IsBufferErased(1, FfsHeader, TestLength)) {
+        break;
+      }
+
+      if (IS_FFS_FILE2(FfsHeader)) {
+        FfsSize = FFS_FILE2_SIZE(FfsHeader);
+      } else {
+        FfsSize = FFS_FILE_SIZE(FfsHeader);
+      }
+
+      if (CompareGuid(FileName, &FfsHeader->Name) &&
+          ((Type == EFI_FV_FILETYPE_ALL) || (FfsHeader->Type == Type))) {
+        //
+        // Check section
+        //
+        *OutFfsBuffer = FfsHeader;
+        *OutFfsBufferSize = FfsSize;
+        return TRUE;
+      } else {
+        //
+        // Any other type is not allowed
+        //
+        DEBUG((DEBUG_INFO, "GetFfsByName - other FFS type 0x%x, name %g\n", FfsHeader->Type, &FfsHeader->Name));
+      }
+
+      //
+      // Next File
+      //
+      FfsHeader = (EFI_FFS_FILE_HEADER *)((UINTN)FfsHeader + ALIGN_VALUE(FfsSize, 8));
+    }
+
+    //
+    // Next FV
+    //
+    FvHeader = (VOID *)(UINTN)((UINTN)FvHeader + FvHeader->FvLength);
+    DEBUG((DEBUG_ERROR, "Next FV....0x%08x - 0x%x\n", FvHeader, FvHeader->FvLength));
+  }
+
+  if (!FvFound) {
+    DEBUG((DEBUG_ERROR, "GetFfsByName - NO FV Found\n"));
+  }
+  return FALSE;
+}
+
+/**
+  Extract the driver FV from an authenticated image.
+
+  @param[in]  AuthenticatedImage      The authenticated capsule image.
+  @param[in]  AuthenticatedImageSize  The size of the authenticated capsule image in bytes.
+  @param[out] DriverFvImage           The driver FV image.
+  @param[out] DriverFvImageSize       The size of the driver FV image in bytes.
+
+  @retval TRUE  The driver Fv is extracted.
+  @retval FALSE The driver Fv is not extracted.
+**/
+BOOLEAN
+EFIAPI
+ExtractDriverFvImage(
+  IN VOID                         *AuthenticatedImage,
+  IN UINTN                        AuthenticatedImageSize,
+  OUT VOID                        **DriverFvImage,
+  OUT UINTN                       *DriverFvImageSize
+  )
+{
+  BOOLEAN     Result;
+  UINT32      FileHeaderSize;
+
+  *DriverFvImage = NULL;
+  *DriverFvImageSize = 0;
+
+  Result = GetFfsByName(AuthenticatedImage, AuthenticatedImageSize, &gEdkiiSystemFmpCapsuleDriverFvFileGuid, EFI_FV_FILETYPE_RAW, DriverFvImage, DriverFvImageSize);
+  if (!Result) {
+    return FALSE;
+  }
+
+  if (IS_FFS_FILE2(*DriverFvImage)) {
+    FileHeaderSize = sizeof(EFI_FFS_FILE_HEADER2);
+  } else {
+    FileHeaderSize = sizeof(EFI_FFS_FILE_HEADER);
+  }
+  *DriverFvImage = (UINT8 *)*DriverFvImage + FileHeaderSize;
+  *DriverFvImageSize = *DriverFvImageSize - FileHeaderSize;
+
+  return Result;
+}
+
+/**
+  Extract the config image from an authenticated image.
+
+  @param[in]  AuthenticatedImage      The authenticated capsule image.
+  @param[in]  AuthenticatedImageSize  The size of the authenticated capsule image in bytes.
+  @param[out] ConfigImage             The config image.
+  @param[out] ConfigImageSize         The size of the config image in bytes.
+
+  @retval TRUE  The config image is extracted.
+  @retval FALSE The config image is not extracted.
+**/
+BOOLEAN
+EFIAPI
+ExtractConfigImage(
+  IN VOID                         *AuthenticatedImage,
+  IN UINTN                        AuthenticatedImageSize,
+  OUT VOID                        **ConfigImage,
+  OUT UINTN                       *ConfigImageSize
+  )
+{
+  BOOLEAN     Result;
+  UINT32      FileHeaderSize;
+
+  *ConfigImage = NULL;
+  *ConfigImageSize = 0;
+
+  Result = GetFfsByName(AuthenticatedImage, AuthenticatedImageSize, &gEdkiiSystemFmpCapsuleConfigFileGuid, EFI_FV_FILETYPE_RAW, ConfigImage, ConfigImageSize);
+  if (!Result) {
+    return FALSE;
+  }
+
+  if (IS_FFS_FILE2(*ConfigImage)) {
+    FileHeaderSize = sizeof(EFI_FFS_FILE_HEADER2);
+  } else {
+    FileHeaderSize = sizeof(EFI_FFS_FILE_HEADER);
+  }
+  *ConfigImage = (UINT8 *)*ConfigImage + FileHeaderSize;
+  *ConfigImageSize = *ConfigImageSize - FileHeaderSize;
+
+  return Result;
+}
+
+/**
+  Extract the authenticated image from an FMP capsule image.
+
+  @param[in]  Image                   The FMP capsule image, including EFI_FIRMWARE_IMAGE_AUTHENTICATION.
+  @param[in]  ImageSize               The size of FMP capsule image in bytes.
+  @param[out] LastAttemptStatus       The last attempt status, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+  @param[out] AuthenticatedImage      The authenticated capsule image, excluding EFI_FIRMWARE_IMAGE_AUTHENTICATION.
+  @param[out] AuthenticatedImageSize  The size of the authenticated capsule image in bytes.
+
+  @retval TRUE  The authenticated image is extracted.
+  @retval FALSE The authenticated image is not extracted.
+**/
+BOOLEAN
+EFIAPI
+ExtractAuthenticatedImage(
+  IN VOID                         *Image,
+  IN UINTN                        ImageSize,
+  OUT UINT32                      *LastAttemptStatus,
+  OUT VOID                        **AuthenticatedImage,
+  OUT UINTN                       *AuthenticatedImageSize
+  )
+{
+  EFI_FIRMWARE_IMAGE_AUTHENTICATION         *ImageAuthentication;
+  UINTN                                     ImageOffset;
+  EFI_STATUS                                Status;
+
+  DEBUG((DEBUG_INFO, "ExtractAuthenticatedImage - Image: 0x%08x - 0x%08x\n", (UINTN)Image, (UINTN)ImageSize));
+
+  *LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;
+
+  Status = ExecuteFmpAuthenticationHandler(
+             Image,
+             ImageSize,
+             LastAttemptStatus
+             );
+  if (EFI_ERROR(Status)) {
+    // Authentication fail
+    DEBUG((DEBUG_ERROR, "ExecuteFmpAuthenticationHandler - %r\n", Status));
+    // LastAttemptStatus might not be updated. Double check.
+    if (*LastAttemptStatus == LAST_ATTEMPT_STATUS_SUCCESS) {
+      *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INVALID_FORMAT;
+    }
+    return FALSE;
+  }
+
+  //
+  // Authentication pass
+  // LastAttemptStatus must be updated.
+  //
+  if (*LastAttemptStatus == LAST_ATTEMPT_STATUS_SUCCESS) {
+    ImageAuthentication = (EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image;
+    ImageOffset = ImageAuthentication->AuthInfo.Hdr.dwLength + sizeof(UINT64);
+    *AuthenticatedImage = (UINT8 *)Image + ImageOffset;
+    *AuthenticatedImageSize = ImageSize - ImageOffset;
+    return TRUE;
+  } else {
+    return FALSE;
+  }
+}
+
+/**
+  Extract ImageFmpInfo from system firmware.
+
+  @param[in]  BiosImage               The BIOS image.
+  @param[in]  BiosImageSize           The size of the BIOS image in bytes.
+  @param[out] ImageFmpInfo            The ImageFmpInfo.
+  @param[out] ImageFmpInfoSize        The size of the ImageFmpInfo in bytes.
+
+  @retval TRUE  The ImageFmpInfo is extracted.
+  @retval FALSE The ImageFmpInfo is not extracted.
+**/
+BOOLEAN
+EFIAPI
+ExtractSystemFirmwareImageFmpInfo(
+  IN VOID                                      *BiosImage,
+  IN UINTN                                     BiosImageSize,
+  OUT EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR   **ImageFmpInfo,
+  OUT UINTN                                    *ImageFmpInfoSize
+  )
+{
+  BOOLEAN     Result;
+  UINT32      SectionHeaderSize;
+  UINT32      FileHeaderSize;
+
+  *ImageFmpInfo = NULL;
+  *ImageFmpInfoSize = 0;
+
+  Result = GetFfsByName(BiosImage, BiosImageSize, &gEdkiiSystemFirmwareImageDescriptorFileGuid, EFI_FV_FILETYPE_ALL, (VOID **)ImageFmpInfo, ImageFmpInfoSize);
+  if (!Result) {
+    return FALSE;
+  }
+  if (IS_FFS_FILE2 (*ImageFmpInfo)) {
+    FileHeaderSize = sizeof(EFI_FFS_FILE_HEADER2);
+  } else {
+    FileHeaderSize = sizeof(EFI_FFS_FILE_HEADER);
+  }
+  *ImageFmpInfo = (VOID *)((UINT8 *)*ImageFmpInfo + FileHeaderSize);
+  *ImageFmpInfoSize = *ImageFmpInfoSize - FileHeaderSize;
+
+  Result = GetSectionByType(*ImageFmpInfo, (UINT32)*ImageFmpInfoSize, EFI_SECTION_RAW, 0, (VOID **)ImageFmpInfo, ImageFmpInfoSize);
+  if (!Result) {
+    return FALSE;
+  }
+  if (IS_SECTION2(*ImageFmpInfo)) {
+    SectionHeaderSize = sizeof(EFI_RAW_SECTION2);
+  } else {
+    SectionHeaderSize = sizeof(EFI_RAW_SECTION);
+  }
+  *ImageFmpInfo = (VOID *)((UINT8 *)*ImageFmpInfo + SectionHeaderSize);
+  *ImageFmpInfoSize = *ImageFmpInfoSize - SectionHeaderSize;
+
+  return TRUE;
+}
+
+/**
+  Extract the BIOS image from an authenticated image.
+
+  @param[in]  AuthenticatedImage      The authenticated capsule image.
+  @param[in]  AuthenticatedImageSize  The size of the authenticated capsule image in bytes.
+  @param[out] BiosImage               The BIOS image.
+  @param[out] BiosImageSize           The size of the BIOS image in bytes.
+
+  @retval TRUE  The BIOS image is extracted.
+  @retval FALSE The BIOS image is not extracted.
+**/
+BOOLEAN
+EFIAPI
+ExtractSystemFirmwareImage(
+  IN VOID                         *AuthenticatedImage,
+  IN UINTN                        AuthenticatedImageSize,
+  OUT VOID                        **BiosImage,
+  OUT UINTN                       *BiosImageSize
+  )
+{
+  BOOLEAN     Result;
+  UINT32      FileHeaderSize;
+
+  *BiosImage = NULL;
+  *BiosImageSize = 0;
+
+  Result = GetFfsByName(AuthenticatedImage, AuthenticatedImageSize, &mEdkiiSystemFirmwareFileGuid, EFI_FV_FILETYPE_RAW, BiosImage, BiosImageSize);
+  if (!Result) {
+    // no nested FV, just return all data.
+    *BiosImage = AuthenticatedImage;
+    *BiosImageSize = AuthenticatedImageSize;
+
+    return TRUE;
+  }
+  if (IS_FFS_FILE2 (*BiosImage)) {
+    FileHeaderSize = sizeof(EFI_FFS_FILE_HEADER2);
+  } else {
+    FileHeaderSize = sizeof(EFI_FFS_FILE_HEADER);
+  }
+  *BiosImage = (UINT8 *)*BiosImage + FileHeaderSize;
+  *BiosImageSize = *BiosImageSize - FileHeaderSize;
+
+  return Result;
+}
+
+/**
+  Authenticated system firmware FMP capsule image.
+
+  @param[in]  Image                   The FMP capsule image, including EFI_FIRMWARE_IMAGE_AUTHENTICATION.
+  @param[in]  ImageSize               The size of FMP capsule image in bytes.
+  @param[in]  ForceVersionMatch       TRUE: The version of capsule must be as same as the version of current image.
+                                      FALSE: The version of capsule must be as same as greater than the lowest
+                                             supported version of current image.
+  @param[out] LastAttemptVersion      The last attempt version, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+  @param[out] LastAttemptStatus       The last attempt status, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+  @param[out] AuthenticatedImage      The authenticated capsule image, excluding EFI_FIRMWARE_IMAGE_AUTHENTICATION.
+  @param[out] AuthenticatedImageSize  The size of the authenticated capsule image in bytes.
+
+  @retval TRUE  Authentication passes and the authenticated image is extracted.
+  @retval FALSE Authentication fails and the authenticated image is not extracted.
+**/
+EFI_STATUS
+EFIAPI
+CapsuleAuthenticateSystemFirmware (
+  IN VOID                         *Image,
+  IN UINTN                        ImageSize,
+  IN BOOLEAN                      ForceVersionMatch,
+  OUT UINT32                      *LastAttemptVersion,
+  OUT UINT32                      *LastAttemptStatus,
+  OUT VOID                        **AuthenticatedImage,
+  OUT UINTN                       *AuthenticatedImageSize
+  )
+{
+  BOOLEAN                                  Result;
+  EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR   *ImageFmpInfo;
+  UINTN                                    ImageFmpInfoSize;
+  EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR   *CurrentImageFmpInfo;
+  UINTN                                    CurrentImageFmpInfoSize;
+  VOID                                     *BiosImage;
+  UINTN                                    BiosImageSize;
+
+  *LastAttemptVersion = 0;
+
+  //
+  // NOTE: This function need run in an isolated environment.
+  // Do not touch FMP protocol and its private structure.
+  //
+
+  Result = ExtractAuthenticatedImage((VOID *)Image, ImageSize, LastAttemptStatus, AuthenticatedImage, AuthenticatedImageSize);
+  if (!Result) {
+    DEBUG((EFI_D_INFO, "ExtractAuthenticatedImage - fail\n"));
+    return EFI_SECURITY_VIOLATION;
+  }
+
+  DEBUG((EFI_D_INFO, "AuthenticatedImage - 0x%x - 0x%x\n", *AuthenticatedImage, *AuthenticatedImageSize));
+
+  Result = ExtractSystemFirmwareImage(*AuthenticatedImage, *AuthenticatedImageSize, &BiosImage, &BiosImageSize);
+  if (!Result) {
+    *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INVALID_FORMAT;
+    DEBUG((EFI_D_INFO, "ExtractBiosImage - fail\n"));
+    return EFI_SECURITY_VIOLATION;
+  }
+  DEBUG((EFI_D_INFO, "BiosImage - 0x%x - 0x%x\n", BiosImage, BiosImageSize));
+
+  Result = ExtractSystemFirmwareImageFmpInfo(BiosImage, BiosImageSize, &ImageFmpInfo, &ImageFmpInfoSize);
+  if (!Result) {
+    *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INVALID_FORMAT;
+    DEBUG((EFI_D_INFO, "ExtractSystemFirmwareImageFmpInfo - fail\n"));
+    return EFI_SECURITY_VIOLATION;
+  }
+
+  *LastAttemptVersion = ImageFmpInfo->Version;
+  DEBUG((EFI_D_INFO, "ImageFmpInfo - 0x%x - 0x%x\n", ImageFmpInfo, ImageFmpInfoSize));
+  DEBUG((EFI_D_INFO, "NewImage Version - 0x%x\n", ImageFmpInfo->Version));
+  DEBUG((EFI_D_INFO, "NewImage LowestSupportedImageVersion - 0x%x\n", ImageFmpInfo->LowestSupportedImageVersion));
+
+  CurrentImageFmpInfo = mImageFmpInfo;
+  CurrentImageFmpInfoSize = mImageFmpInfoSize;
+
+  DEBUG((EFI_D_INFO, "ImageFmpInfo - 0x%x - 0x%x\n", CurrentImageFmpInfo, CurrentImageFmpInfoSize));
+  DEBUG((EFI_D_INFO, "Current Version - 0x%x\n", CurrentImageFmpInfo->Version));
+  DEBUG((EFI_D_INFO, "Current LowestSupportedImageVersion - 0x%x\n", CurrentImageFmpInfo->LowestSupportedImageVersion));
+
+  if (ForceVersionMatch) {
+    if (CurrentImageFmpInfo->Version != ImageFmpInfo->Version) {
+      *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INCORRECT_VERSION;
+      DEBUG((EFI_D_INFO, "ForceVersionMatch check - fail\n"));
+      return EFI_SECURITY_VIOLATION;
+    }
+  } else {
+    if (CurrentImageFmpInfo->Version < ImageFmpInfo->LowestSupportedImageVersion) {
+      *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INCORRECT_VERSION;
+      DEBUG((EFI_D_INFO, "LowestSupportedImageVersion check - fail\n"));
+      return EFI_SECURITY_VIOLATION;
+    }
+  }
+
+  *LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;
+  return EFI_SUCCESS;
+}
+
+/**
+  The constructor function.
+
+  @retval EFI_SUCCESS   The constructor successfully .
+**/
+EFI_STATUS
+EFIAPI
+EdkiiSystemCapsuleLibConstructor(
+  VOID
+  )
+{
+  mImageFmpInfoSize = PcdGetSize(PcdEdkiiSystemFirmwareImageDescriptor);
+  mImageFmpInfo = AllocateCopyPool (mImageFmpInfoSize, PcdGetPtr(PcdEdkiiSystemFirmwareImageDescriptor));
+  ASSERT(mImageFmpInfo != NULL);
+  CopyGuid(&mEdkiiSystemFirmwareFileGuid, PcdGetPtr(PcdEdkiiSystemFirmwareFileGuid));
+  return EFI_SUCCESS;
+}
diff --git a/MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.inf b/MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.inf
new file mode 100644
index 0000000..2657367
--- /dev/null
+++ b/MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.inf
@@ -0,0 +1,55 @@
+## @file
+#  EDKII System Capsule library.
+#
+#  EDKII System Capsule library instance for DXE/PEI post memory phase.
+#
+#  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = EdkiiSystemCapsuleLib
+  MODULE_UNI_FILE                = EdkiiSystemCapsuleLib.uni
+  FILE_GUID                      = 109D5FC6-56E6-481A-88EF-0CB828FBE0F6
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = EdkiiSystemCapsuleLib
+  CONSTRUCTOR                    = EdkiiSystemCapsuleLibConstructor
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64 IPF EBC
+#
+
+[Sources]
+  EdkiiSystemCapsuleLib.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+  BaseLib
+  BaseMemoryLib
+  DebugLib
+  MemoryAllocationLib
+  FmpAuthenticationLib
+
+[Pcd]
+  gEfiMdeModulePkgTokenSpaceGuid.PcdEdkiiSystemFirmwareImageDescriptor
+  gEfiMdeModulePkgTokenSpaceGuid.PcdEdkiiSystemFirmwareFileGuid
+
+[Guids]
+  gEdkiiSystemFirmwareImageDescriptorFileGuid
+  gEdkiiSystemFmpCapsuleConfigFileGuid
+  gEdkiiSystemFmpCapsuleDriverFvFileGuid
+
diff --git a/MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.uni b/MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.uni
new file mode 100644
index 0000000..93e959e
--- /dev/null
+++ b/MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.uni
@@ -0,0 +1,22 @@
+// /** @file
+// EDKII System Capsule library.
+//
+// EDKII System Capsule library instance for DXE/PEI post memory phase.
+//
+// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+//
+// This program and the accompanying materials
+// are licensed and made available under the terms and conditions of the BSD License
+// which accompanies this distribution.  The full text of the license may be found at
+// http://opensource.org/licenses/bsd-license.php
+//
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT             #language en-US "EDKII System Capsule library."
+
+#string STR_MODULE_DESCRIPTION          #language en-US "EDKII System Capsule library instance for DXE/PEI post memory phase."
+
-- 
2.7.4.windows.1



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

* [PATCH 13/45] MdeModulePkg/PlatformFlashAccessLib: Add NULL PlatformFlashAccessLib.
  2016-09-21  6:44 [PATCH 00/45] Add capsule update and recovery sample Jiewen Yao
                   ` (11 preceding siblings ...)
  2016-09-21  6:44 ` [PATCH 12/45] MdeModulePkg/EdkiiSystemCapsuleLib: Add EdkiiSystemCapsuleLib instance Jiewen Yao
@ 2016-09-21  6:44 ` Jiewen Yao
  2016-09-21  6:44 ` [PATCH 14/45] MdeModulePkg/Esrt: Add ESRT_FW_TYPE_SYSTEMFIRMWARE check Jiewen Yao
                   ` (35 subsequent siblings)
  48 siblings, 0 replies; 83+ messages in thread
From: Jiewen Yao @ 2016-09-21  6:44 UTC (permalink / raw)
  To: edk2-devel; +Cc: Feng Tian, Star Zeng, Michael D Kinney, Liming Gao, Chao Zhang

Add NULL instance to pass build.

Cc: Feng Tian <feng.tian@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Chao Zhang <chao.b.zhang@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
---
 MdeModulePkg/Library/PlatformFlashAccessLibNull/PlatformFlashAccessLibNull.c   | 54 ++++++++++++++++++++
 MdeModulePkg/Library/PlatformFlashAccessLibNull/PlatformFlashAccessLibNull.inf | 40 +++++++++++++++
 MdeModulePkg/Library/PlatformFlashAccessLibNull/PlatformFlashAccessLibNull.uni | 21 ++++++++
 3 files changed, 115 insertions(+)

diff --git a/MdeModulePkg/Library/PlatformFlashAccessLibNull/PlatformFlashAccessLibNull.c b/MdeModulePkg/Library/PlatformFlashAccessLibNull/PlatformFlashAccessLibNull.c
new file mode 100644
index 0000000..7bbe37e
--- /dev/null
+++ b/MdeModulePkg/Library/PlatformFlashAccessLibNull/PlatformFlashAccessLibNull.c
@@ -0,0 +1,54 @@
+/** @file
+  Platform flash device access library NULL instance.
+
+  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <PiDxe.h>
+
+#include <Library/BaseMemoryLib.h>
+#include <Library/PlatformFlashAccessLib.h>
+
+UINT64 mInternalFdAddress;
+
+/**
+  Perform flash write opreation.
+
+  @param FirmwareType      The type of firmware.
+  @param FlashAddress      The address of flash device to be accessed.
+  @param FlashAddressType  The type of flash device address.
+  @param Buffer            The pointer to the data buffer.
+  @param Length            The length of data buffer in bytes.
+
+  @retval EFI_SUCCESS           The operation returns successfully.
+  @retval EFI_WRITE_PROTECTED   The flash device is read only.
+  @retval EFI_UNSUPPORTED       The flash device access is unsupported.
+  @retval EFI_INVALID_PARAMETER The input parameter is not valid.
+**/
+EFI_STATUS
+EFIAPI
+PerformFlashWrite(
+  IN PLATFORM_FIRMWARE_TYPE       FirmwareType,
+  IN EFI_PHYSICAL_ADDRESS         FlashAddress,
+  IN FLASH_ADDRESS_TYPE           FlashAddressType,
+  IN VOID                         *Buffer,
+  IN UINTN                        Length
+  )
+{
+  if (FirmwareType >= PlatformFirmwareTypeMax) {
+    return EFI_UNSUPPORTED;
+  }
+  if (FlashAddressType == FlashAddressTypeRelativeAddress) {
+    FlashAddress = FlashAddress + mInternalFdAddress;
+  }
+  CopyMem((VOID *)(UINTN)(FlashAddress), Buffer, Length);
+  return EFI_SUCCESS;
+}
diff --git a/MdeModulePkg/Library/PlatformFlashAccessLibNull/PlatformFlashAccessLibNull.inf b/MdeModulePkg/Library/PlatformFlashAccessLibNull/PlatformFlashAccessLibNull.inf
new file mode 100644
index 0000000..262821d
--- /dev/null
+++ b/MdeModulePkg/Library/PlatformFlashAccessLibNull/PlatformFlashAccessLibNull.inf
@@ -0,0 +1,40 @@
+## @file
+#  Platform flash device access library.
+#
+#  Platform flash device access library NULL instance.
+#
+#  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = PlatformFlashAccessLibNull
+  MODULE_UNI_FILE                = PlatformFlashAccessLibNull.uni
+  FILE_GUID                      = A0534D92-9776-4E4E-9234-C9DC1849DBB5
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = PlatformFlashAccessLib
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64 IPF EBC
+#
+
+[Sources]
+  PlatformFlashAccessLibNull.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+  BaseMemoryLib
diff --git a/MdeModulePkg/Library/PlatformFlashAccessLibNull/PlatformFlashAccessLibNull.uni b/MdeModulePkg/Library/PlatformFlashAccessLibNull/PlatformFlashAccessLibNull.uni
new file mode 100644
index 0000000..ae2648e
--- /dev/null
+++ b/MdeModulePkg/Library/PlatformFlashAccessLibNull/PlatformFlashAccessLibNull.uni
@@ -0,0 +1,21 @@
+// /** @file
+//  Platform flash device access library.
+//
+//  Platform flash device access library NULL instance.
+//
+// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+//
+// This program and the accompanying materials
+// are licensed and made available under the terms and conditions of the BSD License
+// which accompanies this distribution. The full text of the license may be found at
+// http://opensource.org/licenses/bsd-license.php
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT             #language en-US "Platform flash device access library."
+
+#string STR_MODULE_DESCRIPTION          #language en-US "Platform flash device access library NULL instance."
+
-- 
2.7.4.windows.1



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

* [PATCH 14/45] MdeModulePkg/Esrt: Add ESRT_FW_TYPE_SYSTEMFIRMWARE check.
  2016-09-21  6:44 [PATCH 00/45] Add capsule update and recovery sample Jiewen Yao
                   ` (12 preceding siblings ...)
  2016-09-21  6:44 ` [PATCH 13/45] MdeModulePkg/PlatformFlashAccessLib: Add NULL PlatformFlashAccessLib Jiewen Yao
@ 2016-09-21  6:44 ` Jiewen Yao
  2016-09-21  6:44 ` [PATCH 15/45] MdeModulePkg/SystemBiosUpdate: Add SystemBiosUpdate component Jiewen Yao
                   ` (34 subsequent siblings)
  48 siblings, 0 replies; 83+ messages in thread
From: Jiewen Yao @ 2016-09-21  6:44 UTC (permalink / raw)
  To: edk2-devel; +Cc: Feng Tian, Star Zeng, Michael D Kinney, Liming Gao, Chao Zhang

The previous ESRT driver unconditionally treat FMP to be
ESRT_FW_TYPE_DEVICEFIRMWARE.
EDKII System Capsule reuses FMP, but it is ESRT_FW_TYPE_SYSTEMFIRMWARE.

Add check to ImageTypeId check to see if it is ESRT_FW_TYPE_SYSTEMFIRMWARE.

Cc: Feng Tian <feng.tian@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Chao Zhang <chao.b.zhang@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
---
 MdeModulePkg/Universal/EsrtDxe/EsrtDxe.inf |  3 +-
 MdeModulePkg/Universal/EsrtDxe/EsrtImpl.c  | 37 ++++++++++++++++++--
 2 files changed, 37 insertions(+), 3 deletions(-)

diff --git a/MdeModulePkg/Universal/EsrtDxe/EsrtDxe.inf b/MdeModulePkg/Universal/EsrtDxe/EsrtDxe.inf
index 8fbc75b..8b28adc 100644
--- a/MdeModulePkg/Universal/EsrtDxe/EsrtDxe.inf
+++ b/MdeModulePkg/Universal/EsrtDxe/EsrtDxe.inf
@@ -4,7 +4,7 @@
 #  This driver produces EsrtManagement protocol to manage cache ESRT repository for FMP/Non-FMP instances.
 #  ESRT table based on repository is published on gEfiEventReadyToBootGuid.
 #
-#  Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
+#  Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>
 #  This program and the accompanying materials
 #  are licensed and made available under the terms and conditions of the BSD License
 #  which accompanies this distribution.  The full text of the license may be found at
@@ -64,6 +64,7 @@
   gEfiMdeModulePkgTokenSpaceGuid.PcdMaxFmpEsrtCacheNum                  ## CONSUMES
   gEfiMdeModulePkgTokenSpaceGuid.PcdMaxNonFmpEsrtCacheNum               ## CONSUMES
   gEfiMdeModulePkgTokenSpaceGuid.PcdSystemRebootAfterCapsuleProcessFlag ## CONSUMES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdEdkiiSystemFmpCapsuleImageTypeIdGuid  ## CONSUMES
 
 [Depex]
   gEfiVariableArchProtocolGuid AND gEfiVariableWriteArchProtocolGuid
diff --git a/MdeModulePkg/Universal/EsrtDxe/EsrtImpl.c b/MdeModulePkg/Universal/EsrtDxe/EsrtImpl.c
index f6d1e97..f3c03bf 100644
--- a/MdeModulePkg/Universal/EsrtDxe/EsrtImpl.c
+++ b/MdeModulePkg/Universal/EsrtDxe/EsrtImpl.c
@@ -1,7 +1,7 @@
 /** @file
   Esrt management implementation.
 
-Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>
 This program and the accompanying materials
 are licensed and made available under the terms and conditions of the BSD License
 which accompanies this distribution.  The full text of the license may be found at
@@ -391,6 +391,35 @@ EXIT:
 }
 
 /**
+  Return if this FMP is a system FMP or a device FMP, based upon FmpImageInfo.
+
+  @param[in] FmpImageInfo A pointer to EFI_FIRMWARE_IMAGE_DESCRIPTOR
+
+  @return TRUE  It is a system FMP.
+  @return FALSE It is a device FMP.
+**/
+BOOLEAN
+IsSystemFmp (
+  IN EFI_FIRMWARE_IMAGE_DESCRIPTOR   *FmpImageInfo
+  )
+{
+  GUID      *Guid;
+  UINTN     Count;
+  UINTN     Index;
+
+  Guid = PcdGetPtr(PcdEdkiiSystemFmpCapsuleImageTypeIdGuid);
+  Count = PcdGetSize(PcdEdkiiSystemFmpCapsuleImageTypeIdGuid)/sizeof(GUID);
+
+  for (Index = 0; Index < Count; Index++, Guid++) {
+    if (CompareGuid(&FmpImageInfo->ImageTypeId, Guid)) {
+      return TRUE;
+    }
+  }
+
+  return FALSE;
+}
+
+/**
   Init one ESRT entry according to input FmpImageInfo (V1, V2, V3) .
 
   @param[in, out]     EsrtEntry            Esrt entry to be Init
@@ -407,7 +436,11 @@ SetEsrtEntryFromFmpInfo (
 {
   EsrtEntry->FwVersion                = FmpImageInfo->Version;
   EsrtEntry->FwClass                  = FmpImageInfo->ImageTypeId;
-  EsrtEntry->FwType                   = ESRT_FW_TYPE_DEVICEFIRMWARE;
+  if (IsSystemFmp(FmpImageInfo)) {
+    EsrtEntry->FwType                   = ESRT_FW_TYPE_SYSTEMFIRMWARE;
+  } else {
+    EsrtEntry->FwType                   = ESRT_FW_TYPE_DEVICEFIRMWARE;
+  }
   EsrtEntry->LowestSupportedFwVersion = 0;
   EsrtEntry->CapsuleFlags             = 0;
   EsrtEntry->LastAttemptVersion       = 0;
-- 
2.7.4.windows.1



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

* [PATCH 15/45] MdeModulePkg/SystemBiosUpdate: Add SystemBiosUpdate component.
  2016-09-21  6:44 [PATCH 00/45] Add capsule update and recovery sample Jiewen Yao
                   ` (13 preceding siblings ...)
  2016-09-21  6:44 ` [PATCH 14/45] MdeModulePkg/Esrt: Add ESRT_FW_TYPE_SYSTEMFIRMWARE check Jiewen Yao
@ 2016-09-21  6:44 ` Jiewen Yao
  2016-09-21  6:44 ` [PATCH 16/45] MdeModulePkg/RecoveryModuleLoadPei: Add RecoveryModuleLoadPei Jiewen Yao
                   ` (33 subsequent siblings)
  48 siblings, 0 replies; 83+ messages in thread
From: Jiewen Yao @ 2016-09-21  6:44 UTC (permalink / raw)
  To: edk2-devel; +Cc: Feng Tian, Star Zeng, Michael D Kinney, Liming Gao, Chao Zhang

SystemBiosUpdate supports udpate system BIOS via UEFI FMP capsule.

SystemBiosReportDxe.inf can be included in system BIOS. It is a lightweight
FMP protocol implementation and it only reports FMP information, so that
ESRT table can report the system firmware information. It does not support
SetImage().

SystemBiosUpdateDxe.inf can be included in EDKII system capsule image.
It is a full feature FMP protocol implementation and supports SetImage().
It can be used to update the system firmware.
SystemBiosUpdateDxe.inf can also be included in system BIOS.
If so SystemBiosReportDxe.inf is not needed.

SystemBiosUpdateDxe SetImage() will perform the FMP authentication and
version check. If and only if the FMP authentication passes, and new
EDKII system capsule version is no less than current BIOS
LowestSupportedVersion, the system firmware will be udpated.

Cc: Feng Tian <feng.tian@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Chao Zhang <chao.b.zhang@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
---
 MdeModulePkg/Universal/SystemBiosUpdate/ParseConfigProfile.c          | 219 +++++++++
 MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosDxe.h               | 393 ++++++++++++++++
 MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosMainDxe.c           | 484 ++++++++++++++++++++
 MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosMainSetImage.c      | 453 ++++++++++++++++++
 MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosMainSetImageDummy.c |  90 ++++
 MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxe.inf       |  66 +++
 MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxe.uni       |  21 +
 MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxeExtra.uni  |  20 +
 MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxe.inf       |  70 +++
 MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxe.uni       |  21 +
 MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxeExtra.uni  |  20 +
 11 files changed, 1857 insertions(+)

diff --git a/MdeModulePkg/Universal/SystemBiosUpdate/ParseConfigProfile.c b/MdeModulePkg/Universal/SystemBiosUpdate/ParseConfigProfile.c
new file mode 100644
index 0000000..365b8c5
--- /dev/null
+++ b/MdeModulePkg/Universal/SystemBiosUpdate/ParseConfigProfile.c
@@ -0,0 +1,219 @@
+/** @file
+  Parse the INI configuration file and pass the information to the update driver
+  so that the driver can perform update accordingly.
+
+  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions
+  of the BSD License which accompanies this distribution.  The
+  full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "SystemBiosDxe.h"
+#include <Library/IniParsingLib.h>
+#include <Library/PrintLib.h>
+
+#define MAX_LINE_LENGTH           512
+
+/**
+  Parse Config data file to get the updated data array.
+
+  @param DataBuffer      Config raw file buffer.
+  @param BufferSize      Size of raw buffer.
+  @param ConfigHeader    Pointer to the config header.
+  @param UpdateArray     Pointer to the config of update data.
+
+  @retval EFI_NOT_FOUND         No config data is found.
+  @retval EFI_OUT_OF_RESOURCES  No enough memory is allocated.
+  @retval EFI_SUCCESS           Parse the config file successfully.
+
+**/
+EFI_STATUS
+ParseUpdateDataFile (
+  IN      UINT8                         *DataBuffer,
+  IN      UINTN                         BufferSize,
+  IN OUT  CONFIG_HEADER                 *ConfigHeader,
+  IN OUT  UPDATE_CONFIG_DATA            **UpdateArray
+  )
+{
+  EFI_STATUS                            Status;
+  CHAR8                                 *SectionName;
+  CHAR8                                 Entry[MAX_LINE_LENGTH];
+  UINTN                                 Num;
+  UINT64                                Num64;
+  UINTN                                 Index;
+  EFI_GUID                              FileGuid;
+  VOID                                  *Context;
+
+  //
+  // First process the data buffer and get all sections and entries
+  //
+  Context = OpenDataFile(DataBuffer, BufferSize);
+  if (Context == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // Now get NumOfUpdate
+  //
+  Status = GetDecimalUintnFromDataFile(
+             Context,
+             "Head",
+             "NumOfUpdate",
+             &Num
+             );
+  if (EFI_ERROR(Status) || (Num == 0)) {
+    CloseDataFile(Context);
+    return EFI_NOT_FOUND;
+  }
+
+  ConfigHeader->NumOfUpdates = Num;
+  *UpdateArray = AllocateZeroPool ((sizeof (UPDATE_CONFIG_DATA) * Num));
+  if (*UpdateArray == NULL) {
+    CloseDataFile(Context);
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  for (Index = 0 ; Index < ConfigHeader->NumOfUpdates ; Index++) {
+    //
+    // Get the section name of each update
+    //
+    AsciiStrCpyS (Entry, MAX_LINE_LENGTH, "Update");
+    AsciiValueToString(Entry + AsciiStrLen(Entry), 0, Index, 0);
+    Status = GetStringFromDataFile(
+               Context,
+               "Head",
+               Entry,
+               &SectionName
+               );
+    if (EFI_ERROR(Status) || (SectionName == NULL)) {
+      CloseDataFile(Context);
+      return EFI_NOT_FOUND;
+    }
+
+    //
+    // The section name of this update has been found.
+    // Now looks for all the config data of this update
+    //
+    (*UpdateArray)[Index].Index = Index;
+
+    //
+    // ImageTypeId
+    //
+    Status = GetGuidFromDataFile(
+               Context,
+               SectionName,
+               "ImageTypeId",
+               &FileGuid
+               );
+    if (EFI_ERROR(Status)) {
+      ZeroMem(&((*UpdateArray)[Index].ImageTypeId), sizeof(EFI_GUID));
+    } else {
+      CopyGuid(&((*UpdateArray)[Index].ImageTypeId), &FileGuid);
+    }
+
+    //
+    // FirmwareType
+    //
+    Status = GetDecimalUintnFromDataFile(
+               Context,
+               SectionName,
+               "FirmwareType",
+               &Num
+               );
+    if (EFI_ERROR(Status)) {
+      Num = PlatformFirmwareTypeBios;
+    }
+    (*UpdateArray)[Index].FirmwareType = (PLATFORM_FIRMWARE_TYPE) Num;
+
+    //
+    // AddressType
+    //
+    Status = GetDecimalUintnFromDataFile(
+               Context,
+               SectionName,
+               "AddressType",
+               &Num
+               );
+    if (EFI_ERROR(Status)) {
+      CloseDataFile(Context);
+      return EFI_NOT_FOUND;
+    }
+    (*UpdateArray)[Index].AddressType = (FLASH_ADDRESS_TYPE) Num;
+
+    //
+    // BaseAddress
+    //
+    Status = GetHexUint64FromDataFile(
+               Context,
+               SectionName,
+               "BaseAddress",
+               &Num64
+               );
+    if (EFI_ERROR(Status)) {
+      CloseDataFile(Context);
+      return EFI_NOT_FOUND;
+    }
+    (*UpdateArray)[Index].BaseAddress = (EFI_PHYSICAL_ADDRESS) Num64;
+
+    //
+    // FileBuid
+    //
+    Status = GetGuidFromDataFile(
+               Context,
+               SectionName,
+               "FileGuid",
+               &FileGuid
+               );
+    if (EFI_ERROR(Status)) {
+      CloseDataFile(Context);
+      return EFI_NOT_FOUND;
+    }
+
+    CopyGuid(&((*UpdateArray)[Index].FileGuid), &FileGuid);
+
+    //
+    // Length
+    //
+    Status = GetHexUintnFromDataFile(
+               Context,
+               SectionName,
+               "Length",
+               &Num
+               );
+    if (EFI_ERROR(Status)) {
+      CloseDataFile(Context);
+      return EFI_NOT_FOUND;
+    }
+    (*UpdateArray)[Index].Length = (UINTN) Num;
+
+    //
+    // ImageOffset
+    //
+    Status = GetHexUintnFromDataFile(
+               Context,
+               SectionName,
+               "ImageOffset",
+               &Num
+               );
+    if (EFI_ERROR(Status)) {
+      CloseDataFile(Context);
+      return EFI_NOT_FOUND;
+    }
+    (*UpdateArray)[Index].ImageOffset = (UINTN) Num;
+  }
+
+  //
+  // Now all configuration data got. Free those temporary buffers
+  //
+  CloseDataFile(Context);
+
+  return EFI_SUCCESS;
+}
+
diff --git a/MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosDxe.h b/MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosDxe.h
new file mode 100644
index 0000000..ce4cbd0
--- /dev/null
+++ b/MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosDxe.h
@@ -0,0 +1,393 @@
+/** @file
+  System BIOS update header file.
+
+  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _SYSTEM_BIOS_UPDATE_H_
+#define _SYSTEM_BIOS_UPDATE_H_
+
+#include <PiDxe.h>
+
+#include <Guid/SystemResourceTable.h>
+#include <Guid/FirmwareContentsSigned.h>
+#include <Guid/WinCertificate.h>
+#include <Guid/EdkiiSystemFmpCapsule.h>
+
+#include <Protocol/FirmwareManagement.h>
+#include <Protocol/FirmwareVolumeBlock.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/DevicePathLib.h>
+#include <Library/HobLib.h>
+#include <Library/DxeServicesLib.h>
+#include <Library/PlatformFlashAccessLib.h>
+#include <Library/EdkiiSystemCapsuleLib.h>
+
+typedef struct {
+  UINT32 LastAttemptVersion;
+  UINT32 LastAttemptStatus;
+} SYSTEM_FMP_LAST_ATTEMPT_VARIABLE;
+
+#define SYSTEM_FMP_LAST_ATTEMPT_VARIABLE_NAME  L"SystemLastAttempVar"
+
+#define SYSTEM_FMP_LAST_ATTEMPT_VARIABLE_GUID {0x2f564d6f, 0xcc2c, 0x4838, { 0xb9, 0xa8, 0xbe, 0x59, 0x48, 0xb0, 0x3d, 0x59 }}
+
+#define BIOS_FMP_PRIVATE_DATA_SIGNATURE  SIGNATURE_32('B', 'I', 'O', 'F')
+
+//
+// BIOS FMP private data structure.
+//
+
+struct _BIOS_FMP_PRIVATE_DATA {
+  UINT32                                          Signature;
+  EFI_FIRMWARE_MANAGEMENT_PROTOCOL                Fmp;
+  EFI_HANDLE                                      Handle;
+  UINT8                                           DescriptorCount;
+  EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR          *ImageDescriptor;
+  SYSTEM_FMP_LAST_ATTEMPT_VARIABLE                LastAttempt;
+};
+
+typedef struct _BIOS_FMP_PRIVATE_DATA  BIOS_FMP_PRIVATE_DATA;
+
+/**
+  Returns a pointer to the BIOS_FMP_PRIVATE_DATA structure from the input a as Fmp.
+
+  If the signatures matches, then a pointer to the data structure that contains
+  a specified field of that data structure is returned.
+
+  @param  a              Pointer to the field specified by ServiceBinding within
+                         a data structure of type BIOS_FMP_PRIVATE_DATA.
+
+**/
+#define BIOS_FMP_PRIVATE_DATA_FROM_FMP(a) \
+  CR ( \
+  (a), \
+  BIOS_FMP_PRIVATE_DATA, \
+  Fmp, \
+  BIOS_FMP_PRIVATE_DATA_SIGNATURE \
+  )
+
+
+//
+// Update data
+//
+
+typedef struct {
+  UINTN                           NumOfUpdates;
+} CONFIG_HEADER;
+
+typedef struct {
+  UINTN                           Index;
+  EFI_GUID                        ImageTypeId;
+  PLATFORM_FIRMWARE_TYPE          FirmwareType;
+  FLASH_ADDRESS_TYPE              AddressType;
+  EFI_GUID                        FileGuid;
+  EFI_PHYSICAL_ADDRESS            BaseAddress;
+  UINTN                           Length;
+  UINTN                           ImageOffset;
+} UPDATE_CONFIG_DATA;
+
+//
+// System Firmware Update SMM Communication
+//
+
+#define SYSTEM_FIRMWARE_UPDATE_COMMUNICATION_FUNCTION_SET_IMAGE 1
+
+typedef struct {
+  UINTN       Function;
+  EFI_STATUS  ReturnStatus;
+//UINT8       Data[];
+} SYSTEM_FIRMWARE_UPDATE_COMMUNICATION_HEAD;
+
+#define  ABORT_REASON_MAX_SIZE              0x40  // UnicodeStringSize including final L'\0'
+
+#define  CAPSULE_IMAGE_ADDITIONAL_MAX_SIZE  (0x20020 + 0xA0000) // Addtional size for Capsule Header, FV block alignment + DispatchImage.
+
+typedef struct {
+  UINT8       ImageIndex;
+  UINTN       ImageSize;
+  UINTN       AbortReasonSize;
+  UINT32      LastAttemptVersion;
+  UINT32      LastAttemptStatus;
+//UINT8       Data[AbortReasonMaxSize + ImageSize];
+} SYSTEM_FIRMWARE_UPDATE_COMMUNICATION_SET_IMAGE;
+
+
+/**
+  Returns information about the current firmware image(s) of the device.
+
+  This function allows a copy of the current firmware image to be created and saved.
+  The saved copy could later been used, for example, in firmware image recovery or rollback.
+
+  @param[in]      This               A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
+  @param[in, out] ImageInfoSize      A pointer to the size, in bytes, of the ImageInfo buffer.
+                                     On input, this is the size of the buffer allocated by the caller.
+                                     On output, it is the size of the buffer returned by the firmware
+                                     if the buffer was large enough, or the size of the buffer needed
+                                     to contain the image(s) information if the buffer was too small.
+  @param[in, out] ImageInfo          A pointer to the buffer in which firmware places the current image(s)
+                                     information. The information is an array of EFI_FIRMWARE_IMAGE_DESCRIPTORs.
+  @param[out]     DescriptorVersion  A pointer to the location in which firmware returns the version number
+                                     associated with the EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+  @param[out]     DescriptorCount    A pointer to the location in which firmware returns the number of
+                                     descriptors or firmware images within this device.
+  @param[out]     DescriptorSize     A pointer to the location in which firmware returns the size, in bytes,
+                                     of an individual EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+  @param[out]     PackageVersion     A version number that represents all the firmware images in the device.
+                                     The format is vendor specific and new version must have a greater value
+                                     than the old version. If PackageVersion is not supported, the value is
+                                     0xFFFFFFFF. A value of 0xFFFFFFFE indicates that package version comparison
+                                     is to be performed using PackageVersionName. A value of 0xFFFFFFFD indicates
+                                     that package version update is in progress.
+  @param[out]     PackageVersionName A pointer to a pointer to a null-terminated string representing the
+                                     package version name. The buffer is allocated by this function with
+                                     AllocatePool(), and it is the caller's responsibility to free it with a call
+                                     to FreePool().
+
+  @retval EFI_SUCCESS                The device was successfully updated with the new image.
+  @retval EFI_BUFFER_TOO_SMALL       The ImageInfo buffer was too small. The current buffer size
+                                     needed to hold the image(s) information is returned in ImageInfoSize.
+  @retval EFI_INVALID_PARAMETER      ImageInfoSize is NULL.
+  @retval EFI_DEVICE_ERROR           Valid information could not be returned. Possible corrupted image.
+
+**/
+EFI_STATUS
+EFIAPI
+FmpGetImageInfo(
+  IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL       *This,
+  IN OUT    UINTN                           *ImageInfoSize,
+  IN OUT    EFI_FIRMWARE_IMAGE_DESCRIPTOR   *ImageInfo,
+  OUT       UINT32                          *DescriptorVersion,
+  OUT       UINT8                           *DescriptorCount,
+  OUT       UINTN                           *DescriptorSize,
+  OUT       UINT32                          *PackageVersion,
+  OUT       CHAR16                          **PackageVersionName
+  );
+
+/**
+  Retrieves a copy of the current firmware image of the device.
+
+  This function allows a copy of the current firmware image to be created and saved.
+  The saved copy could later been used, for example, in firmware image recovery or rollback.
+
+  @param[in]     This            A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
+  @param[in]     ImageIndex      A unique number identifying the firmware image(s) within the device.
+                                 The number is between 1 and DescriptorCount.
+  @param[in,out] Image           Points to the buffer where the current image is copied to.
+  @param[in,out] ImageSize       On entry, points to the size of the buffer pointed to by Image, in bytes.
+                                 On return, points to the length of the image, in bytes.
+
+  @retval EFI_SUCCESS            The device was successfully updated with the new image.
+  @retval EFI_BUFFER_TOO_SMALL   The buffer specified by ImageSize is too small to hold the
+                                 image. The current buffer size needed to hold the image is returned
+                                 in ImageSize.
+  @retval EFI_INVALID_PARAMETER  The Image was NULL.
+  @retval EFI_NOT_FOUND          The current image is not copied to the buffer.
+  @retval EFI_UNSUPPORTED        The operation is not supported.
+  @retval EFI_SECURITY_VIOLATIO  The operation could not be performed due to an authentication failure.
+
+**/
+EFI_STATUS
+EFIAPI
+FmpGetImage(
+  IN  EFI_FIRMWARE_MANAGEMENT_PROTOCOL  *This,
+  IN  UINT8                             ImageIndex,
+  IN  OUT  VOID                         *Image,
+  IN  OUT  UINTN                        *ImageSize
+  );
+
+/**
+  Updates the firmware image of the device.
+
+  This function updates the hardware with the new firmware image.
+  This function returns EFI_UNSUPPORTED if the firmware image is not updatable.
+  If the firmware image is updatable, the function should perform the following minimal validations
+  before proceeding to do the firmware image update.
+  - Validate the image authentication if image has attribute
+    IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED. The function returns
+    EFI_SECURITY_VIOLATION if the validation fails.
+  - Validate the image is a supported image for this device. The function returns EFI_ABORTED if
+    the image is unsupported. The function can optionally provide more detailed information on
+    why the image is not a supported image.
+  - Validate the data from VendorCode if not null. Image validation must be performed before
+    VendorCode data validation. VendorCode data is ignored or considered invalid if image
+    validation failed. The function returns EFI_ABORTED if the data is invalid.
+
+  VendorCode enables vendor to implement vendor-specific firmware image update policy. Null if
+  the caller did not specify the policy or use the default policy. As an example, vendor can implement
+  a policy to allow an option to force a firmware image update when the abort reason is due to the new
+  firmware image version is older than the current firmware image version or bad image checksum.
+  Sensitive operations such as those wiping the entire firmware image and render the device to be
+  non-functional should be encoded in the image itself rather than passed with the VendorCode.
+  AbortReason enables vendor to have the option to provide a more detailed description of the abort
+  reason to the caller.
+
+  @param[in]  This               A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
+  @param[in]  ImageIndex         A unique number identifying the firmware image(s) within the device.
+                                 The number is between 1 and DescriptorCount.
+  @param[in]  Image              Points to the new image.
+  @param[in]  ImageSize          Size of the new image in bytes.
+  @param[in]  VendorCode         This enables vendor to implement vendor-specific firmware image update policy.
+                                 Null indicates the caller did not specify the policy or use the default policy.
+  @param[in]  Progress           A function used by the driver to report the progress of the firmware update.
+  @param[out] AbortReason        A pointer to a pointer to a null-terminated string providing more
+                                 details for the aborted operation. The buffer is allocated by this function
+                                 with AllocatePool(), and it is the caller's responsibility to free it with a
+                                 call to FreePool().
+
+  @retval EFI_SUCCESS            The device was successfully updated with the new image.
+  @retval EFI_ABORTED            The operation is aborted.
+  @retval EFI_INVALID_PARAMETER  The Image was NULL.
+  @retval EFI_UNSUPPORTED        The operation is not supported.
+  @retval EFI_SECURITY_VIOLATIO  The operation could not be performed due to an authentication failure.
+
+**/
+EFI_STATUS
+EFIAPI
+FmpSetImage(
+  IN  EFI_FIRMWARE_MANAGEMENT_PROTOCOL                 *This,
+  IN  UINT8                                            ImageIndex,
+  IN  CONST VOID                                       *Image,
+  IN  UINTN                                            ImageSize,
+  IN  CONST VOID                                       *VendorCode,
+  IN  EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS    Progress,
+  OUT CHAR16                                           **AbortReason
+  );
+
+/**
+  Checks if the firmware image is valid for the device.
+
+  This function allows firmware update application to validate the firmware image without
+  invoking the SetImage() first.
+
+  @param[in]  This               A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
+  @param[in]  ImageIndex         A unique number identifying the firmware image(s) within the device.
+                                 The number is between 1 and DescriptorCount.
+  @param[in]  Image              Points to the new image.
+  @param[in]  ImageSize          Size of the new image in bytes.
+  @param[out] ImageUpdatable     Indicates if the new image is valid for update. It also provides,
+                                 if available, additional information if the image is invalid.
+
+  @retval EFI_SUCCESS            The image was successfully checked.
+  @retval EFI_INVALID_PARAMETER  The Image was NULL.
+  @retval EFI_UNSUPPORTED        The operation is not supported.
+  @retval EFI_SECURITY_VIOLATIO  The operation could not be performed due to an authentication failure.
+
+**/
+EFI_STATUS
+EFIAPI
+FmpCheckImage(
+  IN  EFI_FIRMWARE_MANAGEMENT_PROTOCOL  *This,
+  IN  UINT8                             ImageIndex,
+  IN  CONST VOID                        *Image,
+  IN  UINTN                             ImageSize,
+  OUT UINT32                            *ImageUpdatable
+  );
+
+/**
+  Returns information about the firmware package.
+
+  This function returns package information.
+
+  @param[in]  This                     A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
+  @param[out] PackageVersion           A version number that represents all the firmware images in the device.
+                                       The format is vendor specific and new version must have a greater value
+                                       than the old version. If PackageVersion is not supported, the value is
+                                       0xFFFFFFFF. A value of 0xFFFFFFFE indicates that package version
+                                       comparison is to be performed using PackageVersionName. A value of
+                                       0xFFFFFFFD indicates that package version update is in progress.
+  @param[out] PackageVersionName       A pointer to a pointer to a null-terminated string representing
+                                       the package version name. The buffer is allocated by this function with
+                                       AllocatePool(), and it is the caller's responsibility to free it with a
+                                       call to FreePool().
+  @param[out] PackageVersionNameMaxLen The maximum length of package version name if device supports update of
+                                       package version name. A value of 0 indicates the device does not support
+                                       update of package version name. Length is the number of Unicode characters,
+                                       including the terminating null character.
+  @param[out] AttributesSupported      Package attributes that are supported by this device. See 'Package Attribute
+                                       Definitions' for possible returned values of this parameter. A value of 1
+                                       indicates the attribute is supported and the current setting value is
+                                       indicated in AttributesSetting. A value of 0 indicates the attribute is not
+                                       supported and the current setting value in AttributesSetting is meaningless.
+  @param[out] AttributesSetting        Package attributes. See 'Package Attribute Definitions' for possible returned
+                                       values of this parameter
+
+  @retval EFI_SUCCESS                  The package information was successfully returned.
+  @retval EFI_UNSUPPORTED              The operation is not supported.
+
+**/
+EFI_STATUS
+EFIAPI
+FmpGetPackageInfo(
+  IN  EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This,
+  OUT UINT32                           *PackageVersion,
+  OUT CHAR16                           **PackageVersionName,
+  OUT UINT32                           *PackageVersionNameMaxLen,
+  OUT UINT64                           *AttributesSupported,
+  OUT UINT64                           *AttributesSetting
+  );
+
+/**
+  Updates information about the firmware package.
+
+  This function updates package information.
+  This function returns EFI_UNSUPPORTED if the package information is not updatable.
+  VendorCode enables vendor to implement vendor-specific package information update policy.
+  Null if the caller did not specify this policy or use the default policy.
+
+  @param[in]  This               A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
+  @param[in]  Image              Points to the authentication image.
+                                 Null if authentication is not required.
+  @param[in]  ImageSize          Size of the authentication image in bytes.
+                                 0 if authentication is not required.
+  @param[in]  VendorCode         This enables vendor to implement vendor-specific firmware
+                                 image update policy.
+                                 Null indicates the caller did not specify this policy or use
+                                 the default policy.
+  @param[in]  PackageVersion     The new package version.
+  @param[in]  PackageVersionName A pointer to the new null-terminated Unicode string representing
+                                 the package version name.
+                                 The string length is equal to or less than the value returned in
+                                 PackageVersionNameMaxLen.
+
+  @retval EFI_SUCCESS            The device was successfully updated with the new package
+                                 information.
+  @retval EFI_INVALID_PARAMETER  The PackageVersionName length is longer than the value
+                                 returned in PackageVersionNameMaxLen.
+  @retval EFI_UNSUPPORTED        The operation is not supported.
+  @retval EFI_SECURITY_VIOLATIO  The operation could not be performed due to an authentication failure.
+
+**/
+EFI_STATUS
+EFIAPI
+FmpSetPackageInfo(
+  IN  EFI_FIRMWARE_MANAGEMENT_PROTOCOL   *This,
+  IN  CONST VOID                         *Image,
+  IN  UINTN                              ImageSize,
+  IN  CONST VOID                         *VendorCode,
+  IN  UINT32                             PackageVersion,
+  IN  CONST CHAR16                       *PackageVersionName
+  );
+
+extern EFI_GUID gSystemFmpLastAttemptVariableGuid;
+extern EFI_GUID mCurrentImageTypeId;
+
+#endif
+
diff --git a/MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosMainDxe.c b/MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosMainDxe.c
new file mode 100644
index 0000000..d3c2aeb
--- /dev/null
+++ b/MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosMainDxe.c
@@ -0,0 +1,484 @@
+/** @file
+  Produce FMP instance for system firmware.
+
+  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "SystemBiosDxe.h"
+
+EFI_GUID gSystemFmpLastAttemptVariableGuid = SYSTEM_FMP_LAST_ATTEMPT_VARIABLE_GUID;
+
+//
+// BiosFmp driver private data
+//
+BIOS_FMP_PRIVATE_DATA *mBiosFmpPrivate = NULL;
+
+EFI_FIRMWARE_MANAGEMENT_PROTOCOL mFirmwareManagementProtocol = {
+  FmpGetImageInfo,
+  FmpGetImage,
+  FmpSetImage,
+  FmpCheckImage,
+  FmpGetPackageInfo,
+  FmpSetPackageInfo
+};
+
+/**
+  Returns information about the current firmware image(s) of the device.
+
+  This function allows a copy of the current firmware image to be created and saved.
+  The saved copy could later been used, for example, in firmware image recovery or rollback.
+
+  @param[in]      This               A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
+  @param[in, out] ImageInfoSize      A pointer to the size, in bytes, of the ImageInfo buffer.
+                                     On input, this is the size of the buffer allocated by the caller.
+                                     On output, it is the size of the buffer returned by the firmware
+                                     if the buffer was large enough, or the size of the buffer needed
+                                     to contain the image(s) information if the buffer was too small.
+  @param[in, out] ImageInfo          A pointer to the buffer in which firmware places the current image(s)
+                                     information. The information is an array of EFI_FIRMWARE_IMAGE_DESCRIPTORs.
+  @param[out]     DescriptorVersion  A pointer to the location in which firmware returns the version number
+                                     associated with the EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+  @param[out]     DescriptorCount    A pointer to the location in which firmware returns the number of
+                                     descriptors or firmware images within this device.
+  @param[out]     DescriptorSize     A pointer to the location in which firmware returns the size, in bytes,
+                                     of an individual EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+  @param[out]     PackageVersion     A version number that represents all the firmware images in the device.
+                                     The format is vendor specific and new version must have a greater value
+                                     than the old version. If PackageVersion is not supported, the value is
+                                     0xFFFFFFFF. A value of 0xFFFFFFFE indicates that package version comparison
+                                     is to be performed using PackageVersionName. A value of 0xFFFFFFFD indicates
+                                     that package version update is in progress.
+  @param[out]     PackageVersionName A pointer to a pointer to a null-terminated string representing the
+                                     package version name. The buffer is allocated by this function with
+                                     AllocatePool(), and it is the caller's responsibility to free it with a call
+                                     to FreePool().
+
+  @retval EFI_SUCCESS                The device was successfully updated with the new image.
+  @retval EFI_BUFFER_TOO_SMALL       The ImageInfo buffer was too small. The current buffer size
+                                     needed to hold the image(s) information is returned in ImageInfoSize.
+  @retval EFI_INVALID_PARAMETER      ImageInfoSize is NULL.
+  @retval EFI_DEVICE_ERROR           Valid information could not be returned. Possible corrupted image.
+
+**/
+EFI_STATUS
+EFIAPI
+FmpGetImageInfo (
+  IN        EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This,
+  IN OUT    UINTN                            *ImageInfoSize,
+  IN OUT    EFI_FIRMWARE_IMAGE_DESCRIPTOR    *ImageInfo,
+  OUT       UINT32                           *DescriptorVersion,
+  OUT       UINT8                            *DescriptorCount,
+  OUT       UINTN                            *DescriptorSize,
+  OUT       UINT32                           *PackageVersion,
+  OUT       CHAR16                           **PackageVersionName
+  )
+{
+  BIOS_FMP_PRIVATE_DATA                  *BiosFmpPrivate;
+  EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR *ImageDescriptor;
+
+  BiosFmpPrivate = BIOS_FMP_PRIVATE_DATA_FROM_FMP(This);
+
+  if(ImageInfoSize == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (*ImageInfoSize < sizeof(EFI_FIRMWARE_IMAGE_DESCRIPTOR) * BiosFmpPrivate->DescriptorCount) {
+    *ImageInfoSize = sizeof(EFI_FIRMWARE_IMAGE_DESCRIPTOR) * BiosFmpPrivate->DescriptorCount;
+    return EFI_BUFFER_TOO_SMALL;
+  }
+
+  if (ImageInfo == NULL ||
+      DescriptorVersion == NULL ||
+      DescriptorCount == NULL ||
+      DescriptorSize == NULL ||
+      PackageVersion == NULL ||
+      PackageVersionName == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  *ImageInfoSize      = sizeof(EFI_FIRMWARE_IMAGE_DESCRIPTOR) * BiosFmpPrivate->DescriptorCount;
+  *DescriptorSize     = sizeof(EFI_FIRMWARE_IMAGE_DESCRIPTOR);
+  *DescriptorCount    = BiosFmpPrivate->DescriptorCount;
+  *DescriptorVersion  = EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION;
+
+  //
+  // supports 1 ImageInfo descriptor
+  //
+  ImageDescriptor = BiosFmpPrivate->ImageDescriptor;
+  ImageInfo->ImageIndex = ImageDescriptor->ImageIndex;
+  CopyGuid (&ImageInfo->ImageTypeId, &ImageDescriptor->ImageTypeId);
+  ImageInfo->ImageId = ImageDescriptor->ImageId;
+  if (ImageDescriptor->ImageIdNameStringOffset != 0) {
+    ImageInfo->ImageIdName = (CHAR16 *)((UINTN)ImageDescriptor + ImageDescriptor->ImageIdNameStringOffset);
+  } else {
+    ImageInfo->ImageIdName = NULL;
+  }
+  ImageInfo->Version = ImageDescriptor->Version;
+  if (ImageDescriptor->VersionNameStringOffset != 0) {
+    ImageInfo->VersionName = (CHAR16 *)((UINTN)ImageDescriptor + ImageDescriptor->VersionNameStringOffset);
+  } else {
+    ImageInfo->VersionName = NULL;
+  }
+  ImageInfo->Size = (UINTN)ImageDescriptor->Size;
+  ImageInfo->AttributesSupported = ImageDescriptor->AttributesSupported;
+  ImageInfo->AttributesSetting = ImageDescriptor->AttributesSetting;
+  ImageInfo->Compatibilities = ImageDescriptor->Compatibilities;
+  ImageInfo->LowestSupportedImageVersion = ImageDescriptor->LowestSupportedImageVersion;
+  ImageInfo->LastAttemptVersion = BiosFmpPrivate->LastAttempt.LastAttemptVersion;
+  ImageInfo->LastAttemptStatus = BiosFmpPrivate->LastAttempt.LastAttemptStatus;
+  ImageInfo->HardwareInstance = ImageDescriptor->HardwareInstance;
+
+  //
+  // package version
+  //
+  *PackageVersion = ImageDescriptor->PackageVersion;
+  if (ImageDescriptor->PackageVersionNameStringOffset != 0) {
+    *PackageVersionName = (VOID *)((UINTN)ImageDescriptor + ImageDescriptor->PackageVersionNameStringOffset);
+    *PackageVersionName = AllocateCopyPool(StrSize(*PackageVersionName), *PackageVersionName);
+  } else {
+    *PackageVersionName = NULL;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Retrieves a copy of the current firmware image of the device.
+
+  This function allows a copy of the current firmware image to be created and saved.
+  The saved copy could later been used, for example, in firmware image recovery or rollback.
+
+  @param[in]     This            A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
+  @param[in]     ImageIndex      A unique number identifying the firmware image(s) within the device.
+                                 The number is between 1 and DescriptorCount.
+  @param[in,out] Image           Points to the buffer where the current image is copied to.
+  @param[in,out] ImageSize       On entry, points to the size of the buffer pointed to by Image, in bytes.
+                                 On return, points to the length of the image, in bytes.
+
+  @retval EFI_SUCCESS            The device was successfully updated with the new image.
+  @retval EFI_BUFFER_TOO_SMALL   The buffer specified by ImageSize is too small to hold the
+                                 image. The current buffer size needed to hold the image is returned
+                                 in ImageSize.
+  @retval EFI_INVALID_PARAMETER  The Image was NULL.
+  @retval EFI_NOT_FOUND          The current image is not copied to the buffer.
+  @retval EFI_UNSUPPORTED        The operation is not supported.
+  @retval EFI_SECURITY_VIOLATIO  The operation could not be performed due to an authentication failure.
+
+**/
+EFI_STATUS
+EFIAPI
+FmpGetImage(
+  IN  EFI_FIRMWARE_MANAGEMENT_PROTOCOL  *This,
+  IN  UINT8                             ImageIndex,
+  IN  OUT  VOID                         *Image,
+  IN  OUT  UINTN                        *ImageSize
+  )
+{
+  BIOS_FMP_PRIVATE_DATA *BiosFmpPrivate;
+
+  if (Image == NULL || ImageSize == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  BiosFmpPrivate = BIOS_FMP_PRIVATE_DATA_FROM_FMP(This);
+
+  if (ImageIndex == 0 || ImageIndex > BiosFmpPrivate->DescriptorCount || ImageSize == NULL || Image == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  return EFI_UNSUPPORTED;
+}
+
+/**
+  Checks if the firmware image is valid for the device.
+
+  This function allows firmware update application to validate the firmware image without
+  invoking the SetImage() first.
+
+  @param[in]  This               A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
+  @param[in]  ImageIndex         A unique number identifying the firmware image(s) within the device.
+                                 The number is between 1 and DescriptorCount.
+  @param[in]  Image              Points to the new image.
+  @param[in]  ImageSize          Size of the new image in bytes.
+  @param[out] ImageUpdatable     Indicates if the new image is valid for update. It also provides,
+                                 if available, additional information if the image is invalid.
+
+  @retval EFI_SUCCESS            The image was successfully checked.
+  @retval EFI_INVALID_PARAMETER  The Image was NULL.
+  @retval EFI_UNSUPPORTED        The operation is not supported.
+  @retval EFI_SECURITY_VIOLATIO  The operation could not be performed due to an authentication failure.
+
+**/
+EFI_STATUS
+EFIAPI
+FmpCheckImage(
+  IN  EFI_FIRMWARE_MANAGEMENT_PROTOCOL  *This,
+  IN  UINT8                             ImageIndex,
+  IN  CONST VOID                        *Image,
+  IN  UINTN                             ImageSize,
+  OUT UINT32                            *ImageUpdatable
+  )
+{
+  return EFI_UNSUPPORTED;
+}
+
+/**
+  Returns information about the firmware package.
+
+  This function returns package information.
+
+  @param[in]  This                     A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
+  @param[out] PackageVersion           A version number that represents all the firmware images in the device.
+                                       The format is vendor specific and new version must have a greater value
+                                       than the old version. If PackageVersion is not supported, the value is
+                                       0xFFFFFFFF. A value of 0xFFFFFFFE indicates that package version
+                                       comparison is to be performed using PackageVersionName. A value of
+                                       0xFFFFFFFD indicates that package version update is in progress.
+  @param[out] PackageVersionName       A pointer to a pointer to a null-terminated string representing
+                                       the package version name. The buffer is allocated by this function with
+                                       AllocatePool(), and it is the caller's responsibility to free it with a
+                                       call to FreePool().
+  @param[out] PackageVersionNameMaxLen The maximum length of package version name if device supports update of
+                                       package version name. A value of 0 indicates the device does not support
+                                       update of package version name. Length is the number of Unicode characters,
+                                       including the terminating null character.
+  @param[out] AttributesSupported      Package attributes that are supported by this device. See 'Package Attribute
+                                       Definitions' for possible returned values of this parameter. A value of 1
+                                       indicates the attribute is supported and the current setting value is
+                                       indicated in AttributesSetting. A value of 0 indicates the attribute is not
+                                       supported and the current setting value in AttributesSetting is meaningless.
+  @param[out] AttributesSetting        Package attributes. See 'Package Attribute Definitions' for possible returned
+                                       values of this parameter
+
+  @retval EFI_SUCCESS                  The package information was successfully returned.
+  @retval EFI_UNSUPPORTED              The operation is not supported.
+
+**/
+EFI_STATUS
+EFIAPI
+FmpGetPackageInfo(
+  IN  EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This,
+  OUT UINT32                           *PackageVersion,
+  OUT CHAR16                           **PackageVersionName,
+  OUT UINT32                           *PackageVersionNameMaxLen,
+  OUT UINT64                           *AttributesSupported,
+  OUT UINT64                           *AttributesSetting
+  )
+{
+  return EFI_UNSUPPORTED;
+}
+
+/**
+  Updates information about the firmware package.
+
+  This function updates package information.
+  This function returns EFI_UNSUPPORTED if the package information is not updatable.
+  VendorCode enables vendor to implement vendor-specific package information update policy.
+  Null if the caller did not specify this policy or use the default policy.
+
+  @param[in]  This               A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
+  @param[in]  Image              Points to the authentication image.
+                                 Null if authentication is not required.
+  @param[in]  ImageSize          Size of the authentication image in bytes.
+                                 0 if authentication is not required.
+  @param[in]  VendorCode         This enables vendor to implement vendor-specific firmware
+                                 image update policy.
+                                 Null indicates the caller did not specify this policy or use
+                                 the default policy.
+  @param[in]  PackageVersion     The new package version.
+  @param[in]  PackageVersionName A pointer to the new null-terminated Unicode string representing
+                                 the package version name.
+                                 The string length is equal to or less than the value returned in
+                                 PackageVersionNameMaxLen.
+
+  @retval EFI_SUCCESS            The device was successfully updated with the new package
+                                 information.
+  @retval EFI_INVALID_PARAMETER  The PackageVersionName length is longer than the value
+                                 returned in PackageVersionNameMaxLen.
+  @retval EFI_UNSUPPORTED        The operation is not supported.
+  @retval EFI_SECURITY_VIOLATIO  The operation could not be performed due to an authentication failure.
+
+**/
+EFI_STATUS
+EFIAPI
+FmpSetPackageInfo(
+  IN  EFI_FIRMWARE_MANAGEMENT_PROTOCOL   *This,
+  IN  CONST VOID                         *Image,
+  IN  UINTN                              ImageSize,
+  IN  CONST VOID                         *VendorCode,
+  IN  UINT32                             PackageVersion,
+  IN  CONST CHAR16                       *PackageVersionName
+  )
+{
+  return EFI_UNSUPPORTED;
+}
+
+/**
+  Initialize BiosFmpDriver private data structure.
+
+  @param BiosFmpPrivate  private data structure to be initialized.
+
+  @return EFI_SUCCESS private data is initialized.
+**/
+EFI_STATUS
+InitializePrivateData(
+  IN BIOS_FMP_PRIVATE_DATA *BiosFmpPrivate
+  )
+{
+  EFI_STATUS       VarStatus;
+  UINTN            VarSize;
+
+  BiosFmpPrivate->Signature       = BIOS_FMP_PRIVATE_DATA_SIGNATURE;
+  BiosFmpPrivate->Handle          = NULL;
+  BiosFmpPrivate->DescriptorCount = 1;
+  CopyMem(&BiosFmpPrivate->Fmp, &mFirmwareManagementProtocol, sizeof(EFI_FIRMWARE_MANAGEMENT_PROTOCOL));
+
+  BiosFmpPrivate->ImageDescriptor = PcdGetPtr(PcdEdkiiSystemFirmwareImageDescriptor);
+
+  BiosFmpPrivate->LastAttempt.LastAttemptVersion = 0x0;
+  BiosFmpPrivate->LastAttempt.LastAttemptStatus = 0x0;
+  VarSize = sizeof(BiosFmpPrivate->LastAttempt);
+  VarStatus = gRT->GetVariable(
+                     SYSTEM_FMP_LAST_ATTEMPT_VARIABLE_NAME,
+                     &gSystemFmpLastAttemptVariableGuid,
+                     NULL,
+                     &VarSize,
+                     &BiosFmpPrivate->LastAttempt
+                     );
+  DEBUG((EFI_D_INFO, "GetLastAttemp - %r\n", VarStatus));
+  DEBUG((EFI_D_INFO, "GetLastAttemp Version - 0x%x, State - 0x%x\n", BiosFmpPrivate->LastAttempt.LastAttemptVersion, BiosFmpPrivate->LastAttempt.LastAttemptStatus));
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Return if this FMP is a system FMP or a device FMP, based upon FmpImageInfo.
+
+  @param[in] FmpImageInfo A pointer to EFI_FIRMWARE_IMAGE_DESCRIPTOR
+
+  @retval TRUE  It is a system FMP.
+  @retval FALSE It is a device FMP.
+**/
+BOOLEAN
+IsSystemFmp(
+  IN EFI_FIRMWARE_IMAGE_DESCRIPTOR   *FmpImageInfo
+  )
+{
+  GUID      *Guid;
+  UINTN     Count;
+  UINTN     Index;
+
+  Guid = PcdGetPtr(PcdEdkiiSystemFmpCapsuleImageTypeIdGuid);
+  Count = PcdGetSize(PcdEdkiiSystemFmpCapsuleImageTypeIdGuid) / sizeof(GUID);
+
+  for (Index = 0; Index < Count; Index++, Guid++) {
+    if (CompareGuid(&FmpImageInfo->ImageTypeId, Guid)) {
+      return TRUE;
+    }
+  }
+
+  return FALSE;
+}
+
+/**
+  System BIOS FMP module entrypoint
+
+  @param  ImageHandle       The firmware allocated handle for the EFI image.
+  @param  SystemTable       A pointer to the EFI System Table.
+
+  @return EFI_SUCCESS System BIOS FMP module is initialized.
+**/
+EFI_STATUS
+EFIAPI
+BiosUpdateMainDxe(
+  IN EFI_HANDLE                         ImageHandle,
+  IN EFI_SYSTEM_TABLE                   *SystemTable
+  )
+{
+  EFI_STATUS                                      Status;
+  EFI_FIRMWARE_MANAGEMENT_PROTOCOL                *Fmp;
+  UINTN                                           NoHandles;
+  EFI_HANDLE                                      *HandleBuffer;
+  UINTN                                           Index;
+  EFI_FIRMWARE_IMAGE_DESCRIPTOR                   *FmpImageInfo;
+  UINTN                                           ImageInfoSize;
+  UINT32                                          DescriptorVersion;
+  UINT8                                           DescriptorCount;
+  UINTN                                           DescriptorSize;
+  UINT32                                          PackageVersion;
+  CHAR16                                          *PackageVersionName;
+
+  //
+  // Make sure only one instance in system
+  //
+  Status = gBS->LocateHandleBuffer(ByProtocol, &gEfiFirmwareManagementProtocolGuid, NULL, &NoHandles, &HandleBuffer);
+  if (!EFI_ERROR(Status)) {
+    for (Index = 0; Index < NoHandles; Index++) {
+      Status = gBS->HandleProtocol(HandleBuffer[Index], &gEfiFirmwareManagementProtocolGuid, (VOID **)&Fmp);
+      if (EFI_ERROR(Status)) {
+        continue;
+      }
+      ImageInfoSize = 0;
+      Status = Fmp->GetImageInfo (Fmp, &ImageInfoSize, NULL, NULL, NULL, NULL, NULL, NULL);
+      if (Status == EFI_BUFFER_TOO_SMALL) {
+        FmpImageInfo = AllocateZeroPool(ImageInfoSize);
+        if (FmpImageInfo == NULL) {
+          return EFI_OUT_OF_RESOURCES;
+        }
+      } else {
+        continue;
+      }
+      Status = Fmp->GetImageInfo (Fmp, &ImageInfoSize, FmpImageInfo, &DescriptorVersion, &DescriptorCount, &DescriptorSize, &PackageVersion, &PackageVersionName);
+      if (!IsSystemFmp(FmpImageInfo)) {
+        FreePool(FmpImageInfo);
+        continue;
+      }
+      FreePool(FmpImageInfo);
+      Status = gBS->UninstallProtocolInterface(HandleBuffer[Index], &gEfiFirmwareManagementProtocolGuid, Fmp);
+      if (EFI_ERROR(Status)) {
+        DEBUG((EFI_D_ERROR, "Fail to uninstall Fmp - 0x%x\n"));
+      }
+    }
+    FreePool(HandleBuffer);
+  }
+
+  //
+  // Initialize BiosFmpPrivateData
+  //
+  mBiosFmpPrivate = AllocateZeroPool (sizeof(BIOS_FMP_PRIVATE_DATA));
+  if (mBiosFmpPrivate == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  Status = InitializePrivateData(mBiosFmpPrivate);
+  if (EFI_ERROR(Status)) {
+    FreePool(mBiosFmpPrivate);
+    mBiosFmpPrivate = NULL;
+    return Status;
+  }
+
+  //
+  // Install FMP protocol.
+  //
+  Status = gBS->InstallProtocolInterface (
+                  &mBiosFmpPrivate->Handle,
+                  &gEfiFirmwareManagementProtocolGuid,
+                  EFI_NATIVE_INTERFACE,
+                  &mBiosFmpPrivate->Fmp
+                  );
+  if (EFI_ERROR (Status)) {
+    FreePool(mBiosFmpPrivate);
+    mBiosFmpPrivate = NULL;
+    return Status;
+  }
+
+  return Status;
+}
diff --git a/MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosMainSetImage.c b/MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosMainSetImage.c
new file mode 100644
index 0000000..a5cf77c
--- /dev/null
+++ b/MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosMainSetImage.c
@@ -0,0 +1,453 @@
+/** @file
+  SetImage instance to update system firmware.
+
+  Caution: This module requires additional review when modified.
+  This module will have external input - capsule image.
+  This external input must be validated carefully to avoid security issue like
+  buffer overflow, integer overflow.
+
+  FmpSetImage() will receive untrusted input and do basic validation.
+
+  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "SystemBiosDxe.h"
+
+EFI_GUID mCurrentImageTypeId;
+
+BOOLEAN  mNvRamUpdated = FALSE;
+
+/**
+  Parse Config data file to get the updated data array.
+
+  @param DataBuffer      Config raw file buffer.
+  @param BufferSize      Size of raw buffer.
+  @param ConfigHeader    Pointer to the config header.
+  @param UpdateArray     Pointer to the config of update data.
+
+  @retval EFI_NOT_FOUND         No config data is found.
+  @retval EFI_OUT_OF_RESOURCES  No enough memory is allocated.
+  @retval EFI_SUCCESS           Parse the config file successfully.
+
+**/
+EFI_STATUS
+ParseUpdateDataFile(
+  IN      UINT8                         *DataBuffer,
+  IN      UINTN                         BufferSize,
+  IN OUT  CONFIG_HEADER                 *ConfigHeader,
+  IN OUT  UPDATE_CONFIG_DATA            **UpdateArray
+  );
+
+/**
+  Update BIOS image component.
+
+  @param[in]  BiosImage         Points to the BIOS image.
+  @param[in]  BiosImageSize     The length of the BIOS image in bytes.
+  @param[in]  ConfigData         Points to the component configuration structure.
+  @param[out] LastAttemptVersion The last attempt version, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+  @param[out] LastAttemptStatus  The last attempt status, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+
+  @retval EFI_SUCCESS             The BIOS image is updated.
+  @retval EFI_WRITE_PROTECTED     The flash device is read only.
+**/
+EFI_STATUS
+PerformUpdate (
+  IN VOID                         *BiosImage,
+  IN UINTN                        BiosImageSize,
+  IN UPDATE_CONFIG_DATA           *ConfigData,
+  OUT UINT32                      *LastAttemptVersion,
+  OUT UINT32                      *LastAttemptStatus
+  )
+{
+  EFI_STATUS                   Status;
+
+  DEBUG((EFI_D_INFO, "PlatformUpdate:"));
+  DEBUG((EFI_D_INFO, "  BaseAddress - 0x%lx,", ConfigData->BaseAddress));
+  DEBUG((EFI_D_INFO, "  ImageOffset - 0x%x,", ConfigData->ImageOffset));
+  DEBUG((EFI_D_INFO, "  Legnth - 0x%x\n", ConfigData->Length));
+  Status = PerformFlashWrite (
+             ConfigData->FirmwareType,
+             ConfigData->BaseAddress,
+             ConfigData->AddressType,
+             (VOID *)((UINTN)BiosImage + (UINTN)ConfigData->ImageOffset),
+             ConfigData->Length
+             );
+  if (!EFI_ERROR(Status)) {
+    *LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;
+    if (ConfigData->FirmwareType == PlatformFirmwareTypeNvRam) {
+      mNvRamUpdated = TRUE;
+    }
+  } else {
+    *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL;
+  }
+  return Status;
+}
+
+/**
+  Update BIOS image.
+
+  @param[in]  BiosImage         Points to the BIOS image.
+  @param[in]  BiosImageSize     The length of the BIOS image in bytes.
+  @param[in]  ConfigImage       Points to the config file image.
+  @param[in]  ConfigImageSize   The length of the config file image in bytes.
+  @param[out] LastAttemptVersion The last attempt version, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+  @param[out] LastAttemptStatus  The last attempt status, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+
+  @retval EFI_SUCCESS             The BIOS image is updated.
+  @retval EFI_WRITE_PROTECTED     The flash device is read only.
+**/
+EFI_STATUS
+UpdateImage(
+  IN VOID                         *BiosImage,
+  IN UINTN                        BiosImageSize,
+  IN VOID                         *ConfigImage,
+  IN UINTN                        ConfigImageSize,
+  OUT UINT32                      *LastAttemptVersion,
+  OUT UINT32                      *LastAttemptStatus
+  )
+{
+  EFI_STATUS                            Status;
+  UPDATE_CONFIG_DATA                    *ConfigData;
+  UPDATE_CONFIG_DATA                    *UpdateConfigData;
+  CONFIG_HEADER                         ConfigHeader;
+  UINTN                                 Index;
+
+  if (ConfigImage == NULL) {
+    DEBUG((EFI_D_INFO, "PlatformUpdate (NoConfig):"));
+    DEBUG((EFI_D_INFO, "  BaseAddress - 0x%x,", 0));
+    DEBUG((EFI_D_INFO, "  Length - 0x%x\n", BiosImageSize));
+    // ASSUME the whole BIOS include NVRAM region.
+    Status = PerformFlashWrite (
+               PlatformFirmwareTypeNvRam,
+               0,
+               FlashAddressTypeRelativeAddress,
+               BiosImage,
+               BiosImageSize
+               );
+    if (!EFI_ERROR(Status)) {
+      *LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;
+      mNvRamUpdated = TRUE;
+    } else {
+      *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL;
+    }
+    return Status;
+  }
+
+  ConfigData        = NULL;
+  ZeroMem (&ConfigHeader, sizeof(ConfigHeader));
+  Status            = ParseUpdateDataFile (
+                        ConfigImage,
+                        ConfigImageSize,
+                        &ConfigHeader,
+                        &ConfigData
+                        );
+
+  Index = 0;
+  UpdateConfigData = ConfigData;
+  while (Index < ConfigHeader.NumOfUpdates) {
+    if (IsZeroGuid(&UpdateConfigData->ImageTypeId) || CompareGuid(&UpdateConfigData->ImageTypeId, &mCurrentImageTypeId)) {
+      Status = PerformUpdate (
+                 BiosImage,
+                 BiosImageSize,
+                 UpdateConfigData,
+                 LastAttemptVersion,
+                 LastAttemptStatus
+                 );
+      //
+      // Shall updates be serialized so that if an update is not successfully completed,
+      // the remaining updates won't be performed.
+      //
+      if (EFI_ERROR (Status)) {
+        break;
+      }
+    }
+
+    Index++;
+    UpdateConfigData++;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Authenticate and update BIOS image.
+
+  @param[in]  Image              The EDKII system FMP capsule image.
+  @param[in]  ImageSize          The size of the EDKII system FMP capsule image in bytes.
+  @param[out] LastAttemptVersion The last attempt version, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+  @param[out] LastAttemptStatus  The last attempt status, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+
+  @retval EFI_SUCCESS             EDKII system FMP capsule passes authentication and the BIOS image is updated.
+  @retval EFI_SECURITY_VIOLATION  EDKII system FMP capsule fails authentication and the BIOS image is not updated.
+  @retval EFI_WRITE_PROTECTED     The flash device is read only.
+**/
+EFI_STATUS
+BiosAuthenticatedUpdate(
+  IN VOID                         *Image,
+  IN UINTN                        ImageSize,
+  OUT UINT32                      *LastAttemptVersion,
+  OUT UINT32                      *LastAttemptStatus
+  )
+{
+  EFI_STATUS                  Status;
+  VOID                        *BiosImage;
+  UINTN                       BiosImageSize;
+  VOID                        *ConfigImage;
+  UINTN                       ConfigImageSize;
+  VOID                        *AuthenticatedImage;
+  UINTN                       AuthenticatedImageSize;
+
+  DEBUG((EFI_D_INFO, "BiosAuthenticatedUpdate...\n"));
+
+  Status = CapsuleAuthenticateSystemFirmware(Image, ImageSize, FALSE, LastAttemptVersion, LastAttemptStatus, &AuthenticatedImage, &AuthenticatedImageSize);
+  if (EFI_ERROR(Status)) {
+    DEBUG((EFI_D_INFO, "BiosAuthenticateImage - %r\n", Status));
+    return Status;
+  }
+
+  ExtractSystemFirmwareImage(AuthenticatedImage, AuthenticatedImageSize, &BiosImage, &BiosImageSize);
+  ExtractConfigImage(AuthenticatedImage, AuthenticatedImageSize, &ConfigImage, &ConfigImageSize);
+
+  Status = UpdateImage(BiosImage, BiosImageSize, ConfigImage, ConfigImageSize, LastAttemptVersion, LastAttemptStatus);
+  if (EFI_ERROR(Status)) {
+    DEBUG((EFI_D_INFO, "UpdateImage - %r\n", Status));
+    return Status;
+  }
+
+  DEBUG((EFI_D_INFO, "BiosAuthenticatedUpdate Done\n"));
+
+  return EFI_SUCCESS;
+}
+
+/**
+
+  This code finds variable in storage blocks (Volatile or Non-Volatile).
+
+  @param VariableName               Name of Variable to be found.
+  @param VendorGuid                 Variable vendor GUID.
+  @param Attributes                 Attribute value of the variable found.
+  @param DataSize                   Size of Data found. If size is less than the
+                                    data, this value contains the required size.
+  @param Data                       Data pointer.
+
+  @return EFI_INVALID_PARAMETER     Invalid parameter.
+  @return EFI_SUCCESS               Find the specified variable.
+  @return EFI_NOT_FOUND             Not found.
+  @return EFI_BUFFER_TO_SMALL       DataSize is too small for the result.
+
+**/
+EFI_STATUS
+EFIAPI
+GetVariableHook (
+  IN      CHAR16            *VariableName,
+  IN      EFI_GUID          *VendorGuid,
+  OUT     UINT32            *Attributes OPTIONAL,
+  IN OUT  UINTN             *DataSize,
+  OUT     VOID              *Data
+  )
+{
+  DEBUG((EFI_D_INFO, "GetVariableHook - %S, %g\n", VariableName, VendorGuid));
+  return EFI_NOT_AVAILABLE_YET;
+}
+
+/**
+
+  This code Finds the Next available variable.
+
+  @param VariableNameSize           Size of the variable name.
+  @param VariableName               Pointer to variable name.
+  @param VendorGuid                 Variable Vendor Guid.
+
+  @return EFI_INVALID_PARAMETER     Invalid parameter.
+  @return EFI_SUCCESS               Find the specified variable.
+  @return EFI_NOT_FOUND             Not found.
+  @return EFI_BUFFER_TO_SMALL       DataSize is too small for the result.
+
+**/
+EFI_STATUS
+EFIAPI
+GetNextVariableNameHook (
+  IN OUT  UINTN             *VariableNameSize,
+  IN OUT  CHAR16            *VariableName,
+  IN OUT  EFI_GUID          *VendorGuid
+  )
+{
+  DEBUG((EFI_D_INFO, "GetNextVariableNameHook - %S, %g\n", VariableName, VendorGuid));
+  return EFI_NOT_AVAILABLE_YET;
+}
+
+/**
+
+  This code sets variable in storage blocks (Volatile or Non-Volatile).
+
+  @param VariableName                     Name of Variable to be found.
+  @param VendorGuid                       Variable vendor GUID.
+  @param Attributes                       Attribute value of the variable found
+  @param DataSize                         Size of Data found. If size is less than the
+                                          data, this value contains the required size.
+  @param Data                             Data pointer.
+
+  @return EFI_INVALID_PARAMETER           Invalid parameter.
+  @return EFI_SUCCESS                     Set successfully.
+  @return EFI_OUT_OF_RESOURCES            Resource not enough to set variable.
+  @return EFI_NOT_FOUND                   Not found.
+  @return EFI_WRITE_PROTECTED             Variable is read-only.
+
+**/
+EFI_STATUS
+EFIAPI
+SetVariableHook (
+  IN CHAR16                  *VariableName,
+  IN EFI_GUID                *VendorGuid,
+  IN UINT32                  Attributes,
+  IN UINTN                   DataSize,
+  IN VOID                    *Data
+  )
+{
+  DEBUG((EFI_D_INFO, "SetVariableHook - %S, %g, 0x%x (0x%x)\n", VariableName, VendorGuid, Attributes, DataSize));
+  return EFI_NOT_AVAILABLE_YET;
+}
+
+/**
+
+  This code returns information about the EFI variables.
+
+  @param Attributes                     Attributes bitmask to specify the type of variables
+                                        on which to return information.
+  @param MaximumVariableStorageSize     Pointer to the maximum size of the storage space available
+                                        for the EFI variables associated with the attributes specified.
+  @param RemainingVariableStorageSize   Pointer to the remaining size of the storage space available
+                                        for EFI variables associated with the attributes specified.
+  @param MaximumVariableSize            Pointer to the maximum size of an individual EFI variables
+                                        associated with the attributes specified.
+
+  @return EFI_SUCCESS                   Query successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+QueryVariableInfoHook (
+  IN  UINT32                 Attributes,
+  OUT UINT64                 *MaximumVariableStorageSize,
+  OUT UINT64                 *RemainingVariableStorageSize,
+  OUT UINT64                 *MaximumVariableSize
+  )
+{
+  DEBUG((EFI_D_INFO, "QueryVariableInfoHook - 0x%x\n", Attributes));
+  return EFI_NOT_AVAILABLE_YET;
+}
+
+/**
+  Updates the firmware image of the device.
+
+  This function updates the hardware with the new firmware image.
+  This function returns EFI_UNSUPPORTED if the firmware image is not updatable.
+  If the firmware image is updatable, the function should perform the following minimal validations
+  before proceeding to do the firmware image update.
+  - Validate the image authentication if image has attribute
+    IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED. The function returns
+    EFI_SECURITY_VIOLATION if the validation fails.
+  - Validate the image is a supported image for this device. The function returns EFI_ABORTED if
+    the image is unsupported. The function can optionally provide more detailed information on
+    why the image is not a supported image.
+  - Validate the data from VendorCode if not null. Image validation must be performed before
+    VendorCode data validation. VendorCode data is ignored or considered invalid if image
+    validation failed. The function returns EFI_ABORTED if the data is invalid.
+
+  VendorCode enables vendor to implement vendor-specific firmware image update policy. Null if
+  the caller did not specify the policy or use the default policy. As an example, vendor can implement
+  a policy to allow an option to force a firmware image update when the abort reason is due to the new
+  firmware image version is older than the current firmware image version or bad image checksum.
+  Sensitive operations such as those wiping the entire firmware image and render the device to be
+  non-functional should be encoded in the image itself rather than passed with the VendorCode.
+  AbortReason enables vendor to have the option to provide a more detailed description of the abort
+  reason to the caller.
+
+  @param[in]  This               A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
+  @param[in]  ImageIndex         A unique number identifying the firmware image(s) within the device.
+                                 The number is between 1 and DescriptorCount.
+  @param[in]  Image              Points to the new image.
+  @param[in]  ImageSize          Size of the new image in bytes.
+  @param[in]  VendorCode         This enables vendor to implement vendor-specific firmware image update policy.
+                                 Null indicates the caller did not specify the policy or use the default policy.
+  @param[in]  Progress           A function used by the driver to report the progress of the firmware update.
+  @param[out] AbortReason        A pointer to a pointer to a null-terminated string providing more
+                                 details for the aborted operation. The buffer is allocated by this function
+                                 with AllocatePool(), and it is the caller's responsibility to free it with a
+                                 call to FreePool().
+
+  @retval EFI_SUCCESS            The device was successfully updated with the new image.
+  @retval EFI_ABORTED            The operation is aborted.
+  @retval EFI_INVALID_PARAMETER  The Image was NULL.
+  @retval EFI_UNSUPPORTED        The operation is not supported.
+  @retval EFI_SECURITY_VIOLATIO  The operation could not be performed due to an authentication failure.
+
+**/
+EFI_STATUS
+EFIAPI
+FmpSetImage(
+  IN  EFI_FIRMWARE_MANAGEMENT_PROTOCOL                 *This,
+  IN  UINT8                                            ImageIndex,
+  IN  CONST VOID                                       *Image,
+  IN  UINTN                                            ImageSize,
+  IN  CONST VOID                                       *VendorCode,
+  IN  EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS    Progress,
+  OUT CHAR16                                           **AbortReason
+  )
+{
+  EFI_STATUS              Status;
+  EFI_STATUS              VarStatus;
+  BIOS_FMP_PRIVATE_DATA   *BiosFmpPrivate;
+
+  if (Image == NULL || AbortReason == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  BiosFmpPrivate = BIOS_FMP_PRIVATE_DATA_FROM_FMP(This);
+  *AbortReason     = NULL;
+
+  if (ImageIndex == 0 || ImageIndex > BiosFmpPrivate->DescriptorCount || Image == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Status = BiosAuthenticatedUpdate((VOID *)Image, ImageSize, &BiosFmpPrivate->LastAttempt.LastAttemptVersion, &BiosFmpPrivate->LastAttempt.LastAttemptStatus);
+  DEBUG((EFI_D_INFO, "SetImage - LastAttemp Version - 0x%x, State - 0x%x\n", BiosFmpPrivate->LastAttempt.LastAttemptVersion, BiosFmpPrivate->LastAttempt.LastAttemptStatus));
+
+  //
+  // If NVRAM is updated, we should no longer touch variable services, because
+  // the current variable driver may not manage the new NVRAM region.
+  //
+  if (mNvRamUpdated) {
+    DEBUG ((EFI_D_INFO, "NvRamUpdated, Update Variable Serivces\n"));
+    gRT->GetVariable         = GetVariableHook;
+    gRT->GetNextVariableName = GetNextVariableNameHook;
+    gRT->SetVariable         = SetVariableHook;
+    gRT->QueryVariableInfo   = QueryVariableInfoHook;
+
+    gRT->Hdr.CRC32 = 0;
+    gBS->CalculateCrc32 (
+          (UINT8 *) &gRT->Hdr,
+          gRT->Hdr.HeaderSize,
+          &gRT->Hdr.CRC32
+          );
+  }
+
+  VarStatus = gRT->SetVariable(
+                     SYSTEM_FMP_LAST_ATTEMPT_VARIABLE_NAME,
+                     &gSystemFmpLastAttemptVariableGuid,
+                     EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
+                     sizeof(BiosFmpPrivate->LastAttempt),
+                     &BiosFmpPrivate->LastAttempt
+                     );
+  DEBUG((EFI_D_INFO, "SetLastAttemp - %r\n", VarStatus));
+
+  return Status;
+}
diff --git a/MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosMainSetImageDummy.c b/MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosMainSetImageDummy.c
new file mode 100644
index 0000000..3a28f7f
--- /dev/null
+++ b/MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosMainSetImageDummy.c
@@ -0,0 +1,90 @@
+/** @file
+  Dummy SetImage instance.
+
+  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "SystemBiosDxe.h"
+
+/**
+  Updates the firmware image of the device.
+
+  This function updates the hardware with the new firmware image.
+  This function returns EFI_UNSUPPORTED if the firmware image is not updatable.
+  If the firmware image is updatable, the function should perform the following minimal validations
+  before proceeding to do the firmware image update.
+  - Validate the image authentication if image has attribute
+    IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED. The function returns
+    EFI_SECURITY_VIOLATION if the validation fails.
+  - Validate the image is a supported image for this device. The function returns EFI_ABORTED if
+    the image is unsupported. The function can optionally provide more detailed information on
+    why the image is not a supported image.
+  - Validate the data from VendorCode if not null. Image validation must be performed before
+    VendorCode data validation. VendorCode data is ignored or considered invalid if image
+    validation failed. The function returns EFI_ABORTED if the data is invalid.
+
+  VendorCode enables vendor to implement vendor-specific firmware image update policy. Null if
+  the caller did not specify the policy or use the default policy. As an example, vendor can implement
+  a policy to allow an option to force a firmware image update when the abort reason is due to the new
+  firmware image version is older than the current firmware image version or bad image checksum.
+  Sensitive operations such as those wiping the entire firmware image and render the device to be
+  non-functional should be encoded in the image itself rather than passed with the VendorCode.
+  AbortReason enables vendor to have the option to provide a more detailed description of the abort
+  reason to the caller.
+
+  @param[in]  This               A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
+  @param[in]  ImageIndex         A unique number identifying the firmware image(s) within the device.
+                                 The number is between 1 and DescriptorCount.
+  @param[in]  Image              Points to the new image.
+  @param[in]  ImageSize          Size of the new image in bytes.
+  @param[in]  VendorCode         This enables vendor to implement vendor-specific firmware image update policy.
+                                 Null indicates the caller did not specify the policy or use the default policy.
+  @param[in]  Progress           A function used by the driver to report the progress of the firmware update.
+  @param[out] AbortReason        A pointer to a pointer to a null-terminated string providing more
+                                 details for the aborted operation. The buffer is allocated by this function
+                                 with AllocatePool(), and it is the caller's responsibility to free it with a
+                                 call to FreePool().
+
+  @retval EFI_SUCCESS            The device was successfully updated with the new image.
+  @retval EFI_ABORTED            The operation is aborted.
+  @retval EFI_INVALID_PARAMETER  The Image was NULL.
+  @retval EFI_UNSUPPORTED        The operation is not supported.
+  @retval EFI_SECURITY_VIOLATIO  The operation could not be performed due to an authentication failure.
+
+**/
+EFI_STATUS
+EFIAPI
+FmpSetImage(
+  IN  EFI_FIRMWARE_MANAGEMENT_PROTOCOL                 *This,
+  IN  UINT8                                            ImageIndex,
+  IN  CONST VOID                                       *Image,
+  IN  UINTN                                            ImageSize,
+  IN  CONST VOID                                       *VendorCode,
+  IN  EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS    Progress,
+  OUT CHAR16                                           **AbortReason
+  )
+{
+  BIOS_FMP_PRIVATE_DATA   *BiosFmpPrivate;
+
+  if (Image == NULL || AbortReason == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  BiosFmpPrivate = BIOS_FMP_PRIVATE_DATA_FROM_FMP(This);
+  *AbortReason     = NULL;
+
+  if (ImageIndex == 0 || ImageIndex > BiosFmpPrivate->DescriptorCount || Image == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  return EFI_UNSUPPORTED;
+}
+
diff --git a/MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxe.inf b/MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxe.inf
new file mode 100644
index 0000000..9cda2ee
--- /dev/null
+++ b/MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxe.inf
@@ -0,0 +1,66 @@
+## @file
+# SystemBios FMP report driver.
+#
+# Produce FMP instance to report system firmware EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+#
+#  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = SystemBiosReportDxe
+  MODULE_UNI_FILE                = SystemBiosReportDxe.uni
+  FILE_GUID                      = BC1A046C-7DBD-41F2-94E5-D7595554CAF4
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = BiosUpdateMainDxe
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = X64
+#
+
+[Sources]
+  SystemBiosMainDxe.c
+  SystemBiosMainSetImageDummy.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+  BaseLib
+  UefiLib
+  BaseMemoryLib
+  DebugLib
+  PcdLib
+  MemoryAllocationLib
+  UefiBootServicesTableLib
+  HobLib
+  UefiRuntimeServicesTableLib
+  UefiDriverEntryPoint
+  DxeServicesLib
+  PrintLib
+
+[Pcd]
+  gEfiMdeModulePkgTokenSpaceGuid.PcdEdkiiSystemFmpCapsuleImageTypeIdGuid  ## CONSUMES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdEdkiiSystemFirmwareImageDescriptor
+
+[Protocols]
+  gEfiFirmwareManagementProtocolGuid
+
+[Depex]
+  gEfiVariableArchProtocolGuid
+
+[UserExtensions.TianoCore."ExtraFiles"]
+  SystemBiosReportDxeExtra.uni
+
diff --git a/MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxe.uni b/MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxe.uni
new file mode 100644
index 0000000..7d6fb22
--- /dev/null
+++ b/MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxe.uni
@@ -0,0 +1,21 @@
+// /** @file
+// SystemBios FMP report driver.
+//
+// Produce FMP instance to report system firmware EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+//
+// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+//
+// This program and the accompanying materials
+// are licensed and made available under the terms and conditions of the BSD License
+// which accompanies this distribution.  The full text of the license may be found at
+// http://opensource.org/licenses/bsd-license.php
+//
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT             #language en-US "SystemBios FMP report driver."
+
+#string STR_MODULE_DESCRIPTION          #language en-US "Produce FMP instance to report system firmware EFI_FIRMWARE_IMAGE_DESCRIPTOR."
diff --git a/MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxeExtra.uni b/MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxeExtra.uni
new file mode 100644
index 0000000..8eb2009
--- /dev/null
+++ b/MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxeExtra.uni
@@ -0,0 +1,20 @@
+// /** @file
+// SystemBiosReportDxe Localized Strings and Content
+//
+// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+//
+// This program and the accompanying materials
+// are licensed and made available under the terms and conditions of the BSD License
+// which accompanies this distribution.  The full text of the license may be found at
+// http://opensource.org/licenses/bsd-license.php
+//
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+// **/
+
+#string STR_PROPERTIES_MODULE_NAME
+#language en-US
+"SystemBiosReport DXE Driver"
+
+
diff --git a/MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxe.inf b/MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxe.inf
new file mode 100644
index 0000000..9e65641
--- /dev/null
+++ b/MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxe.inf
@@ -0,0 +1,70 @@
+## @file
+# SystemBios FMP update driver.
+#
+# Produce FMP instance to update system firmware.
+#
+#  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = SystemBiosUpdateDxe
+  MODULE_UNI_FILE                = SystemBiosUpdateDxe.uni
+  FILE_GUID                      = 0A2FBD15-1C25-407E-8915-60C5652BC2AA
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = BiosUpdateMainDxe
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = X64
+#
+
+[Sources]
+  SystemBiosMainDxe.c
+  SystemBiosMainSetImage.c
+  ParseConfigProfile.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+  BaseLib
+  UefiLib
+  BaseMemoryLib
+  DebugLib
+  PcdLib
+  MemoryAllocationLib
+  UefiBootServicesTableLib
+  HobLib
+  UefiRuntimeServicesTableLib
+  UefiDriverEntryPoint
+  DxeServicesLib
+  EdkiiSystemCapsuleLib
+  PlatformFlashAccessLib
+  IniParsingLib
+  PrintLib
+
+[Pcd]
+  gEfiMdeModulePkgTokenSpaceGuid.PcdEdkiiSystemFmpCapsuleImageTypeIdGuid  ## CONSUMES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdEdkiiSystemFirmwareImageDescriptor
+
+[Protocols]
+  gEfiFirmwareManagementProtocolGuid
+
+[Depex]
+  gEfiVariableArchProtocolGuid
+
+[UserExtensions.TianoCore."ExtraFiles"]
+  SystemBiosUpdateDxeExtra.uni
+
diff --git a/MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxe.uni b/MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxe.uni
new file mode 100644
index 0000000..39ae0e6
--- /dev/null
+++ b/MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxe.uni
@@ -0,0 +1,21 @@
+// /** @file
+// SystemBios FMP update driver.
+//
+// Produce FMP instance to update system firmware.
+//
+// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+//
+// This program and the accompanying materials
+// are licensed and made available under the terms and conditions of the BSD License
+// which accompanies this distribution.  The full text of the license may be found at
+// http://opensource.org/licenses/bsd-license.php
+//
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT             #language en-US "SystemBios FMP update driver."
+
+#string STR_MODULE_DESCRIPTION          #language en-US "Produce FMP instance to update system firmware."
diff --git a/MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxeExtra.uni b/MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxeExtra.uni
new file mode 100644
index 0000000..0ec28bc
--- /dev/null
+++ b/MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxeExtra.uni
@@ -0,0 +1,20 @@
+// /** @file
+// SystemBiosUpdateDxe Localized Strings and Content
+//
+// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+//
+// This program and the accompanying materials
+// are licensed and made available under the terms and conditions of the BSD License
+// which accompanies this distribution.  The full text of the license may be found at
+// http://opensource.org/licenses/bsd-license.php
+//
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+// **/
+
+#string STR_PROPERTIES_MODULE_NAME
+#language en-US
+"SystemBiosUpdate DXE Driver"
+
+
-- 
2.7.4.windows.1



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

* [PATCH 16/45] MdeModulePkg/RecoveryModuleLoadPei: Add RecoveryModuleLoadPei.
  2016-09-21  6:44 [PATCH 00/45] Add capsule update and recovery sample Jiewen Yao
                   ` (14 preceding siblings ...)
  2016-09-21  6:44 ` [PATCH 15/45] MdeModulePkg/SystemBiosUpdate: Add SystemBiosUpdate component Jiewen Yao
@ 2016-09-21  6:44 ` Jiewen Yao
  2016-09-21  6:44 ` [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application Jiewen Yao
                   ` (32 subsequent siblings)
  48 siblings, 0 replies; 83+ messages in thread
From: Jiewen Yao @ 2016-09-21  6:44 UTC (permalink / raw)
  To: edk2-devel; +Cc: Feng Tian, Star Zeng, Michael D Kinney, Liming Gao, Chao Zhang

RecoveryModuleLoadPei supports recovery system BIOS via UEFI FMP capsule.

RecoveryModuleLoadPei produces EFI_PEI_RECOVERY_MODULE_PPI. It is invoked
by DxeIpl in recovery boot mode.

LoadRecoveryCapsule() will scan all possible
gEfiPeiDeviceRecoveryModulePpiGuid and get EDKII system FMP capsule there.

LoadRecoveryCapsule() will perform the FMP authentication and version
check. If and only if the FMP authentication passes, and EDKII system FMP
capsule version is equal to the current BIOS Version, the recovery will
be performed. Or this capsule image is discard.

Cc: Feng Tian <feng.tian@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Chao Zhang <chao.b.zhang@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
---
 MdeModulePkg/Universal/RecoveryModuleLoadPei/ParseConfigProfile.c           | 158 +++++
 MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPei.c        | 746 ++++++++++++++++++++
 MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPei.h        |  44 ++
 MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPei.inf      |  71 ++
 MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPei.uni      |  21 +
 MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPeiExtra.uni |  20 +
 6 files changed, 1060 insertions(+)

diff --git a/MdeModulePkg/Universal/RecoveryModuleLoadPei/ParseConfigProfile.c b/MdeModulePkg/Universal/RecoveryModuleLoadPei/ParseConfigProfile.c
new file mode 100644
index 0000000..1d739cb
--- /dev/null
+++ b/MdeModulePkg/Universal/RecoveryModuleLoadPei/ParseConfigProfile.c
@@ -0,0 +1,158 @@
+/** @file
+  Parse the INI configuration file and pass the information to the recovery driver
+  so that the driver can perform recovery accordingly.
+
+  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions
+  of the BSD License which accompanies this distribution.  The
+  full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "RecoveryModuleLoadPei.h"
+#include <Library/IniParsingLib.h>
+#include <Library/PrintLib.h>
+
+#define MAX_LINE_LENGTH           512
+
+/**
+  Parse Config data file to get the updated data array.
+
+  @param DataBuffer      Config raw file buffer.
+  @param BufferSize      Size of raw buffer.
+  @param ConfigHeader    Pointer to the config header.
+  @param RecoveryArray   Pointer to the config of recovery data.
+
+  @retval EFI_NOT_FOUND         No config data is found.
+  @retval EFI_OUT_OF_RESOURCES  No enough memory is allocated.
+  @retval EFI_SUCCESS           Parse the config file successfully.
+
+**/
+EFI_STATUS
+ParseRecoveryDataFile (
+  IN      UINT8                         *DataBuffer,
+  IN      UINTN                         BufferSize,
+  IN OUT  CONFIG_HEADER                 *ConfigHeader,
+  IN OUT  RECOVERY_CONFIG_DATA          **RecoveryArray
+  )
+{
+  EFI_STATUS                            Status;
+  CHAR8                                 *SectionName;
+  CHAR8                                 Entry[MAX_LINE_LENGTH];
+  UINTN                                 Num;
+  UINTN                                 Index;
+  EFI_GUID                              FileGuid;
+  VOID                                  *Context;
+
+  //
+  // First process the data buffer and get all sections and entries
+  //
+  Context = OpenDataFile(DataBuffer, BufferSize);
+  if (Context == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // Now get NumOfUpdate
+  //
+  Status = GetDecimalUintnFromDataFile(
+             Context,
+             "Head",
+             "NumOfRecovery",
+             &Num
+             );
+  if (EFI_ERROR(Status) || (Num == 0)) {
+    CloseDataFile(Context);
+    return EFI_NOT_FOUND;
+  }
+
+  ConfigHeader->NumOfRecovery = Num;
+  *RecoveryArray = AllocateZeroPool ((sizeof (RECOVERY_CONFIG_DATA) * Num));
+  if (*RecoveryArray == NULL) {
+    CloseDataFile(Context);
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  for (Index = 0 ; Index < ConfigHeader->NumOfRecovery; Index++) {
+    //
+    // Get the section name of each update
+    //
+    AsciiStrCpyS (Entry, MAX_LINE_LENGTH, "Recovery");
+    AsciiValueToString(Entry + AsciiStrLen(Entry), 0, Index, 0);
+    Status = GetStringFromDataFile(
+               Context,
+               "Head",
+               Entry,
+               &SectionName
+               );
+    if (EFI_ERROR(Status) || (SectionName == NULL)) {
+      CloseDataFile(Context);
+      return EFI_NOT_FOUND;
+    }
+
+    //
+    // The section name of this update has been found.
+    // Now looks for all the config data of this update
+    //
+
+    //
+    // FileBuid
+    //
+    Status = GetGuidFromDataFile(
+               Context,
+               SectionName,
+               "FileGuid",
+               &FileGuid
+               );
+    if (EFI_ERROR(Status)) {
+      CloseDataFile(Context);
+      return EFI_NOT_FOUND;
+    }
+
+    CopyMem (&((*RecoveryArray)[Index].FileGuid), &FileGuid, sizeof(EFI_GUID));
+
+    //
+    // Length
+    //
+    Status = GetHexUintnFromDataFile(
+               Context,
+               SectionName,
+               "Length",
+               &Num
+               );
+    if (EFI_ERROR(Status)) {
+      CloseDataFile(Context);
+      return EFI_NOT_FOUND;
+    }
+    (*RecoveryArray)[Index].Length = Num;
+
+    //
+    // ImageOffset
+    //
+    Status = GetHexUintnFromDataFile(
+               Context,
+               SectionName,
+               "ImageOffset",
+               &Num
+               );
+    if (EFI_ERROR(Status)) {
+      CloseDataFile(Context);
+      return EFI_NOT_FOUND;
+    }
+    (*RecoveryArray)[Index].ImageOffset = Num;
+  }
+
+  //
+  // Now all configuration data got. Free those temporary buffers
+  //
+  CloseDataFile(Context);
+
+  return EFI_SUCCESS;
+}
+
diff --git a/MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPei.c b/MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPei.c
new file mode 100644
index 0000000..9369df5
--- /dev/null
+++ b/MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPei.c
@@ -0,0 +1,746 @@
+/** @file
+  Recovery module.
+
+  Caution: This module requires additional review when modified.
+  This module will have external input - capsule image.
+  This external input must be validated carefully to avoid security issue like
+  buffer overflow, integer overflow.
+
+  ProcessRecoveryCapsule(), ProcessFmpCapsuleImage(), ProcessRecoveryImage() will
+  receive untrusted input and do basic validation.
+
+Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution.  The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+//
+// 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/BootInRecoveryMode.h>
+#include <Ppi/RecoveryModule.h>
+#include <Ppi/DeviceRecoveryModule.h>
+#include <Ppi/FirmwareVolumeInfo.h>
+#include <Guid/FirmwareFileSystem2.h>
+#include <Guid/FmpCapsule.h>
+#include <Guid/EdkiiSystemFmpCapsule.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 "RecoveryModuleLoadPei.h"
+
+/**
+  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.
+
+**/
+EFI_STATUS
+EFIAPI
+LoadRecoveryCapsule(
+  IN EFI_PEI_SERVICES                     **PeiServices,
+  IN EFI_PEI_RECOVERY_MODULE_PPI          *This
+  );
+
+EFI_PEI_RECOVERY_MODULE_PPI mRecoveryPpi = {
+  LoadRecoveryCapsule
+};
+
+EFI_PEI_PPI_DESCRIPTOR mRecoveryPpiList = {
+  (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+  &gEfiPeiRecoveryModulePpiGuid,
+  &mRecoveryPpi
+};
+
+/**
+  Parse Config data file to get the updated data array.
+
+  @param DataBuffer      Config raw file buffer.
+  @param BufferSize      Size of raw buffer.
+  @param ConfigHeader    Pointer to the config header.
+  @param RecoveryArray   Pointer to the config of recovery data.
+
+  @retval EFI_NOT_FOUND         No config data is found.
+  @retval EFI_OUT_OF_RESOURCES  No enough memory is allocated.
+  @retval EFI_SUCCESS           Parse the config file successfully.
+
+**/
+EFI_STATUS
+ParseRecoveryDataFile(
+  IN      UINT8                         *DataBuffer,
+  IN      UINTN                         BufferSize,
+  IN OUT  CONFIG_HEADER                 *ConfigHeader,
+  IN OUT  RECOVERY_CONFIG_DATA          **RecoveryArray
+  );
+
+/**
+  Return if this FMP is a system FMP or a device FMP, based upon FmpImageInfo.
+
+  @param[in] FmpImageHeader A pointer to EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
+
+  @return TRUE  It is a system FMP.
+  @return FALSE It is a device FMP.
+**/
+BOOLEAN
+IsSystemFmpImage (
+  IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER   *FmpImageHeader
+  )
+{
+  GUID      *Guid;
+  UINTN     Count;
+  UINTN     Index;
+
+  Guid = PcdGetPtr(PcdEdkiiSystemFmpCapsuleImageTypeIdGuid);
+  Count = PcdGetSize(PcdEdkiiSystemFmpCapsuleImageTypeIdGuid) / sizeof(GUID);
+
+  for (Index = 0; Index < Count; Index++, Guid++) {
+    if (CompareGuid(&FmpImageHeader->UpdateImageTypeId, Guid)) {
+      return TRUE;
+    }
+  }
+
+  return FALSE;
+}
+
+/**
+  Return if this CapsuleGuid is a FMP capsule GUID or not.
+
+  @param[in] CapsuleGuid A pointer to EFI_GUID
+
+  @return TRUE  It is a FMP capsule GUID.
+  @return FALSE It is not a FMP capsule GUID.
+**/
+BOOLEAN
+IsFmpCapsuleGuid(
+  IN EFI_GUID  *CapsuleGuid
+  )
+{
+  if (CompareGuid(&gEfiFmpCapsuleGuid, CapsuleGuid)) {
+    return TRUE;
+  }
+
+  return FALSE;
+}
+
+/**
+  This function assumes the input Capusule image already passes basic check in
+  ValidateFmpCapsule().
+
+  Criteria of system FMP capsule is:
+  1) FmpCapsuleHeader->EmbeddedDriverCount is 0.
+  2) FmpCapsuleHeader->PayloadItemCount is not 0.
+  3) All ImageHeader->UpdateImageTypeId matches PcdEdkiiSystemFmpCapsuleImageTypeIdGuid.
+
+  @param  CapsuleHeader    Points to a capsule header.
+
+  @retval TRUE   Input capsule is a correct system FMP capsule.
+  @retval FALSE  Input capsule is not a correct system FMP capsule.
+**/
+BOOLEAN
+IsSystemFmpCapsuleImage (
+  IN EFI_CAPSULE_HEADER *CapsuleHeader
+  )
+{
+  EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER       *FmpCapsuleHeader;
+  EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader;
+  UINT64                                       *ItemOffsetList;
+  UINT32                                       ItemNum;
+  UINTN                                        Index;
+
+  FmpCapsuleHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *) ((UINT8 *) CapsuleHeader + CapsuleHeader->HeaderSize);
+
+  if (FmpCapsuleHeader->EmbeddedDriverCount != 0) {
+    return FALSE;
+  }
+
+  if (FmpCapsuleHeader->PayloadItemCount == 0) {
+    return FALSE;
+  }
+
+  ItemNum = FmpCapsuleHeader->EmbeddedDriverCount + FmpCapsuleHeader->PayloadItemCount;
+
+  ItemOffsetList = (UINT64 *)(FmpCapsuleHeader + 1);
+
+  for (Index = 0; Index < ItemNum; Index++) {
+    ImageHeader  = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *)((UINT8 *)FmpCapsuleHeader + ItemOffsetList[Index]);
+    if (!IsSystemFmpImage(ImageHeader)) {
+      return FALSE;
+    }
+  }
+
+  return TRUE;
+}
+
+/**
+  Validate if it is valid capsule header
+
+  This function assumes the caller provided correct CapsuleHeader pointer
+  and CapsuleSize.
+
+  This function validates the fields in EFI_CAPSULE_HEADER.
+
+  @param  CapsuleHeader    Points to a capsule header.
+  @param  CapsuleSize      Size of the whole capsule image.
+
+**/
+BOOLEAN
+IsValidCapsuleHeader(
+  IN EFI_CAPSULE_HEADER  *CapsuleHeader,
+  IN UINT64              CapsuleSize
+  )
+{
+  if (CapsuleHeader->CapsuleImageSize != CapsuleSize) {
+    return FALSE;
+  }
+  if (CapsuleHeader->HeaderSize >= CapsuleHeader->CapsuleImageSize) {
+    return FALSE;
+  }
+  return TRUE;
+}
+
+/**
+  Validate Fmp capsules layout.
+
+  This function assumes the caller validated the capsule by using
+  IsValidCapsuleHeader(), so that all fields in EFI_CAPSULE_HEADER are correct.
+  The capsule buffer size is CapsuleHeader->CapsuleImageSize.
+
+  This function validates the fields in EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
+  and EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER.
+
+  @param[in]   CapsuleHeader        Points to a capsule header.
+  @param[out]  IsSystemFmp          If it is a system FMP.
+  @param[out]  EmbeddedDriverCount  The EmbeddedDriverCount in the FMP capsule.
+
+  @retval EFI_SUCESS             Input capsule is a correct FMP capsule.
+  @retval EFI_INVALID_PARAMETER  Input capsule is not a correct FMP capsule.
+**/
+EFI_STATUS
+ValidateFmpCapsule (
+  IN EFI_CAPSULE_HEADER *CapsuleHeader,
+  OUT BOOLEAN           *IsSystemFmp, OPTIONAL
+  OUT UINT16            *EmbeddedDriverCount OPTIONAL
+  )
+{
+  EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER       *FmpCapsuleHeader;
+  UINT8                                        *EndOfCapsule;
+  EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader;
+  UINT8                                        *EndOfPayload;
+  UINT64                                       *ItemOffsetList;
+  UINT32                                       ItemNum;
+  UINTN                                        Index;
+  UINTN                                        FmpCapsuleSize;
+  UINTN                                        FmpCapsuleHeaderSize;
+  UINT64                                       FmpImageSize;
+  UINTN                                        FmpImageHeaderSize;
+
+  if (CapsuleHeader->HeaderSize >= CapsuleHeader->CapsuleImageSize) {
+    DEBUG((EFI_D_ERROR, "HeaderSize(0x%x) >= CapsuleImageSize(0x%x)\n", CapsuleHeader->HeaderSize, CapsuleHeader->CapsuleImageSize));
+    return EFI_INVALID_PARAMETER;
+  }
+
+  FmpCapsuleHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *) ((UINT8 *) CapsuleHeader + CapsuleHeader->HeaderSize);
+  EndOfCapsule     = (UINT8 *) CapsuleHeader + CapsuleHeader->CapsuleImageSize;
+  FmpCapsuleSize   = (UINTN)EndOfCapsule - (UINTN)FmpCapsuleHeader;
+
+  if (FmpCapsuleSize < sizeof(EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER)) {
+    DEBUG((EFI_D_ERROR, "FmpCapsuleSize(0x%x) < EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER\n", FmpCapsuleSize));
+    return EFI_INVALID_PARAMETER;
+  }
+
+  // Check EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
+  if (FmpCapsuleHeader->Version != EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION) {
+    DEBUG((EFI_D_ERROR, "FmpCapsuleHeader->Version(0x%x) != EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION\n", FmpCapsuleHeader->Version));
+    return EFI_INVALID_PARAMETER;
+  }
+  ItemOffsetList = (UINT64 *)(FmpCapsuleHeader + 1);
+
+  // No overflow
+  ItemNum = FmpCapsuleHeader->EmbeddedDriverCount + FmpCapsuleHeader->PayloadItemCount;
+
+  if ((FmpCapsuleSize - sizeof(EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER))/sizeof(UINT64) < ItemNum) {
+    DEBUG((EFI_D_ERROR, "ItemNum(0x%x) too big\n", ItemNum));
+    return EFI_INVALID_PARAMETER;
+  }
+  FmpCapsuleHeaderSize = sizeof(EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER) + sizeof(UINT64)*ItemNum;
+
+  // Check ItemOffsetList
+  for (Index = 0; Index < ItemNum; Index++) {
+    if (ItemOffsetList[Index] >= FmpCapsuleSize) {
+      DEBUG((EFI_D_ERROR, "ItemOffsetList[%d](0x%lx) >= FmpCapsuleSize(0x%x)\n", Index, ItemOffsetList[Index], FmpCapsuleSize));
+      return EFI_INVALID_PARAMETER;
+    }
+    if (ItemOffsetList[Index] < FmpCapsuleHeaderSize) {
+      DEBUG((EFI_D_ERROR, "ItemOffsetList[%d](0x%lx) < FmpCapsuleHeaderSize(0x%x)\n", Index, ItemOffsetList[Index], FmpCapsuleHeaderSize));
+      return EFI_INVALID_PARAMETER;
+    }
+    //
+    // All the address in ItemOffsetList must be stored in ascending order
+    //
+    if (Index > 0) {
+      if (ItemOffsetList[Index] <= ItemOffsetList[Index - 1]) {
+        DEBUG((EFI_D_ERROR, "ItemOffsetList[%d](0x%lx) < ItemOffsetList[%d](0x%x)\n", Index, ItemOffsetList[Index], Index, ItemOffsetList[Index - 1]));
+        return EFI_INVALID_PARAMETER;
+      }
+    }
+  }
+
+  // Check EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
+  for (Index = FmpCapsuleHeader->EmbeddedDriverCount; Index < ItemNum; Index++) {
+    ImageHeader  = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *)((UINT8 *)FmpCapsuleHeader + ItemOffsetList[Index]);
+    if (Index == ItemNum - 1) {
+      EndOfPayload = (UINT8 *)((UINTN)EndOfCapsule - (UINTN)FmpCapsuleHeader);
+    } else {
+      EndOfPayload = (UINT8 *)(UINTN)ItemOffsetList[Index+1];
+    }
+    FmpImageSize = (UINTN)EndOfPayload - ItemOffsetList[Index];
+
+    if (FmpImageSize < OFFSET_OF(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER, UpdateHardwareInstance)) {
+      DEBUG((EFI_D_ERROR, "FmpImageSize(0x%lx) < EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER\n", FmpImageSize));
+      return EFI_INVALID_PARAMETER;
+    }
+    FmpImageHeaderSize = sizeof(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER);
+    if ((ImageHeader->Version > EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) ||
+        (ImageHeader->Version < 1)) {
+      DEBUG((EFI_D_ERROR, "ImageHeader->Version(0x%x) Unknown\n", ImageHeader->Version));
+      return EFI_INVALID_PARAMETER;
+    }
+    if (ImageHeader->Version < EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {
+      FmpImageHeaderSize = OFFSET_OF(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER, UpdateHardwareInstance);
+    }
+
+    // No overflow
+    if (FmpImageSize != (UINT64)FmpImageHeaderSize + (UINT64)ImageHeader->UpdateImageSize + (UINT64)ImageHeader->UpdateVendorCodeSize) {
+      DEBUG((EFI_D_ERROR, "FmpImageSize(0x%lx) mismatch, UpdateImageSize(0x%x) UpdateVendorCodeSize(0x%x)\n", FmpImageSize, ImageHeader->UpdateImageSize, ImageHeader->UpdateVendorCodeSize));
+      return EFI_INVALID_PARAMETER;
+    }
+  }
+
+  if (ItemNum == 0) {
+    //
+    // No driver & payload element in FMP
+    //
+    EndOfPayload = (UINT8 *)(FmpCapsuleHeader + 1);
+    if (EndOfPayload != EndOfCapsule) {
+      DEBUG((EFI_D_ERROR, "EndOfPayload(0x%x) mismatch, EndOfCapsule(0x%x)\n", EndOfPayload, EndOfCapsule));
+      return EFI_INVALID_PARAMETER;
+    }
+    return EFI_UNSUPPORTED;
+  }
+
+  //
+  // Check in system FMP capsule
+  //
+  if (IsSystemFmp != NULL) {
+    *IsSystemFmp = IsSystemFmpCapsuleImage(CapsuleHeader);
+  }
+
+  if (EmbeddedDriverCount != NULL) {
+    *EmbeddedDriverCount = FmpCapsuleHeader->EmbeddedDriverCount;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Recovery module entrypoint
+
+  @param FileHandle   Handle of the file being invoked.
+  @param PeiServices  Describes the list of possible PEI Services.
+
+  @return EFI_SUCCESS Recovery module is initialized.
+**/
+EFI_STATUS
+EFIAPI
+InitializeRecoveryModule(
+  IN       EFI_PEI_FILE_HANDLE  FileHandle,
+  IN CONST EFI_PEI_SERVICES     **PeiServices
+  )
+{
+  EFI_STATUS  Status;
+  UINTN       BootMode;
+
+  BootMode = GetBootModeHob();
+  ASSERT(BootMode == BOOT_IN_RECOVERY_MODE);
+
+  Status = (**PeiServices).InstallPpi (PeiServices, &mRecoveryPpiList);
+  ASSERT_EFI_ERROR (Status);
+
+  return Status;
+}
+
+/**
+  Create hob and install FvInfo PPI for recovery capsule.
+
+  @param  FvImage         Points to the DXE FV image.
+  @param  FvImageSize     The length of the DXE FV image in bytes.
+
+  @retval EFI_SUCESS      Create hob and install FvInfo PPI successfully.
+**/
+EFI_STATUS
+EFIAPI
+CreateHobForRecoveryCapsule(
+  IN VOID                                *FvImage,
+  IN UINTN                               FvImageSize
+  )
+{
+  EFI_FIRMWARE_VOLUME_HEADER  *FvHeader;
+
+  FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)FvImage;
+  BuildFvHob((UINT64)(UINTN)FvHeader, FvHeader->FvLength);
+  DEBUG((EFI_D_INFO, "BuildFvHob (FvMain in recovery) - 0x%lx - 0x%lx\n", (UINT64)(UINTN)FvHeader, FvHeader->FvLength));
+
+  PeiServicesInstallFvInfoPpi(
+    NULL,
+    (VOID *)FvHeader,
+    (UINT32)FvHeader->FvLength,
+    NULL,
+    NULL
+    );
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Create recovery context based upon BIOS image and config file.
+
+  @param  BiosImage         Points to the BIOS image.
+  @param  BiosImageSize     The length of the BIOS image in bytes.
+  @param  ConfigImage       Points to the config file image.
+  @param  ConfigImageSize   The length of the config file image in bytes.
+
+  @retval EFI_SUCESS             Process Recovery Image successfully.
+**/
+EFI_STATUS
+RecoverImage (
+  IN VOID                         *BiosImage,
+  IN UINTN                        BiosImageSize,
+  IN VOID                         *ConfigImage,
+  IN UINTN                        ConfigImageSize
+  )
+{
+  EFI_STATUS                            Status;
+  RECOVERY_CONFIG_DATA                  *ConfigData;
+  RECOVERY_CONFIG_DATA                  *RecoveryConfigData;
+  CONFIG_HEADER                         ConfigHeader;
+  UINTN                                 Index;
+
+  if (ConfigImage == NULL) {
+    DEBUG((EFI_D_INFO, "RecoverImage (NoConfig):"));
+    Status = CreateHobForRecoveryCapsule(
+               BiosImage,
+               BiosImageSize
+               );
+    return Status;
+  }
+
+  ConfigData        = NULL;
+  ZeroMem (&ConfigHeader, sizeof(ConfigHeader));
+  Status            = ParseRecoveryDataFile (
+                        ConfigImage,
+                        ConfigImageSize,
+                        &ConfigHeader,
+                        &ConfigData
+                        );
+
+  Index = 0;
+  RecoveryConfigData = ConfigData;
+  while (Index < ConfigHeader.NumOfRecovery) {
+    Status = CreateHobForRecoveryCapsule (
+               (UINT8 *)BiosImage + RecoveryConfigData->ImageOffset,
+               RecoveryConfigData->Length
+               );
+    //
+    // Shall updates be serialized so that if an update is not successfully completed,
+    // the remaining updates won't be performed.
+    //
+    if (EFI_ERROR (Status)) {
+      break;
+    }
+
+    Index++;
+    RecoveryConfigData++;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Process recovery image.
+
+  Caution: This function may receive untrusted input.
+
+  @param  Image         Points to the recovery image.
+  @param  Length        The length of the recovery image in bytes.
+
+  @retval EFI_SUCESS             Process Recovery Image successfully.
+  @retval EFI_SECURITY_VIOLATION Recovery image is not processed due to security violation.
+**/
+EFI_STATUS
+ProcessRecoveryImage (
+  IN VOID  *Image,
+  IN UINTN Length
+  )
+{
+  UINT32                      LastAttemptVersion;
+  UINT32                      LastAttemptStatus;
+  EFI_STATUS                  Status;
+  VOID                        *BiosImage;
+  UINTN                       BiosImageSize;
+  VOID                        *ConfigImage;
+  UINTN                       ConfigImageSize;
+  VOID                        *AuthenticatedImage;
+  UINTN                       AuthenticatedImageSize;
+
+  Status = CapsuleAuthenticateSystemFirmware(Image, Length, TRUE, &LastAttemptVersion, &LastAttemptStatus, &AuthenticatedImage, &AuthenticatedImageSize);
+  if (EFI_ERROR(Status)) {
+    DEBUG((EFI_D_INFO, "CapsuleAuthenticateSystemFirmware - %r\n", Status));
+    return Status;
+  }
+
+  ExtractSystemFirmwareImage(AuthenticatedImage, AuthenticatedImageSize, &BiosImage, &BiosImageSize);
+  ExtractConfigImage(AuthenticatedImage, AuthenticatedImageSize, &ConfigImage, &ConfigImageSize);
+
+  Status = RecoverImage(BiosImage, BiosImageSize, ConfigImage, ConfigImageSize);
+  if (EFI_ERROR(Status)) {
+    DEBUG((EFI_D_INFO, "RecoverImage - %r\n", Status));
+    return Status;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Process Firmware management protocol data capsule.
+
+  Caution: This function may receive untrusted input.
+
+  This function assumes the caller validated the capsule by using
+  ValidateFmpCapsule(), so that all fields in EFI_CAPSULE_HEADER,
+  EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER and
+  EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER are correct.
+
+  @param  CapsuleHeader         Points to a capsule header.
+  @param  IsSystemFmp           If this capsule is a system FMP capsule.
+
+  @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.
+  @retval EFI_OUT_OF_RESOURCES  Not enough memory.
+**/
+EFI_STATUS
+ProcessFmpCapsuleImage (
+  IN EFI_CAPSULE_HEADER *CapsuleHeader,
+  IN BOOLEAN            IsSystemFmp
+  )
+{
+  EFI_STATUS                                    Status;
+  EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER        *FmpCapsuleHeader;
+  EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER  *ImageHeader;
+  UINT8                                         *Image;
+  UINT64                                        *ItemOffsetList;
+  UINTN                                         ItemIndex;
+
+  if (!IsSystemFmp) {
+    return EFI_UNSUPPORTED;
+  }
+
+  FmpCapsuleHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *)((UINT8 *)CapsuleHeader + CapsuleHeader->HeaderSize);
+  ItemOffsetList = (UINT64 *)(FmpCapsuleHeader + 1);
+
+  for (ItemIndex = 0; ItemIndex < FmpCapsuleHeader->PayloadItemCount; ItemIndex++) {
+    ImageHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *)((UINT8 *)FmpCapsuleHeader + ItemOffsetList[ItemIndex]);
+    if (ImageHeader->Version >= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {
+      Image = (UINT8 *)(ImageHeader + 1);
+    } else {
+      //
+      // If the EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER is version 1, only match ImageTypeId.
+      // Header should exclude UpdateHardwareInstance field
+      //
+      Image = (UINT8 *)ImageHeader + OFFSET_OF(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER, UpdateHardwareInstance);
+    }
+
+    Status = ProcessRecoveryImage (Image, ImageHeader->UpdateImageSize);
+    if (EFI_ERROR(Status)) {
+      return Status;
+    }
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Process recovery capsule image.
+
+  Caution: This function may receive untrusted input.
+
+  @param CapsuleBuffer   The capsule image buffer.
+  @param CapsuleSize     The size of the capsule image in bytes.
+
+  @retval EFI_SUCCESS               The recovery capsule is processed.
+  @retval EFI_SECURITY_VIOLATION    The recovery capsule is not process because of security violation.
+  @retval EFI_NOT_FOUND             The recovery capsule is not process because of unrecognization.
+**/
+EFI_STATUS
+EFIAPI
+ProcessRecoveryCapsule (
+  IN VOID                                *CapsuleBuffer,
+  IN UINTN                               CapsuleSize
+  )
+{
+  EFI_STATUS                   Status;
+  BOOLEAN                      IsSystemFmp;
+  EFI_CAPSULE_HEADER           *CapsuleHeader;
+
+  CapsuleHeader = CapsuleBuffer;
+  if (!IsValidCapsuleHeader (CapsuleHeader, CapsuleSize)) {
+    DEBUG((EFI_D_ERROR, "CapsuleImageSize incorrect\n"));
+    return EFI_SECURITY_VIOLATION;
+  }
+
+  //
+  // Check FMP capsule layout
+  //
+  if (IsFmpCapsuleGuid(&CapsuleHeader->CapsuleGuid)) {
+    DEBUG((EFI_D_INFO, "CreateHobForRecoveryCapsule\n"));
+
+    DEBUG((EFI_D_INFO, "ProcessCapsuleImage for FmpCapsule ...\n"));
+    DEBUG((EFI_D_INFO, "ValidateFmpCapsule ...\n"));
+    Status = ValidateFmpCapsule(CapsuleHeader, &IsSystemFmp, NULL);
+    DEBUG((EFI_D_INFO, "ValidateFmpCapsule - %r\n", Status));
+    if (EFI_ERROR(Status)) {
+      return Status;
+    }
+
+    //
+    // Press EFI FMP Capsule
+    //
+    DEBUG((EFI_D_INFO, "ProcessFmpCapsuleImage ...\n"));
+    Status = ProcessFmpCapsuleImage(CapsuleHeader, IsSystemFmp);
+    DEBUG((EFI_D_INFO, "ProcessFmpCapsuleImage - %r\n", Status));
+
+    DEBUG((EFI_D_INFO, "CreateHobForRecoveryCapsule Done\n"));
+    return Status;
+  }
+
+  return EFI_UNSUPPORTED;
+}
+
+/**
+  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.
+
+**/
+EFI_STATUS
+EFIAPI
+LoadRecoveryCapsule(
+  IN EFI_PEI_SERVICES                     **PeiServices,
+  IN EFI_PEI_RECOVERY_MODULE_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, "Recovery Entry\n"));
+
+  for (Instance = 0; ; Instance++) {
+    Status = PeiServicesLocatePpi (
+               &gEfiPeiDeviceRecoveryModulePpiGuid,
+               Instance,
+               NULL,
+               (VOID **)&DeviceRecoveryPpi
+               );
+    DEBUG ((EFI_D_ERROR, "LoadRecoveryCapsule - LocateRecoveryPpi (%d) - %r\n", Instance, Status));
+    if (EFI_ERROR (Status)) {
+      break;
+    }
+    NumberRecoveryCapsules = 0;
+    Status = DeviceRecoveryPpi->GetNumberRecoveryCapsules (
+                                  (EFI_PEI_SERVICES **)PeiServices,
+                                  DeviceRecoveryPpi,
+                                  &NumberRecoveryCapsules
+                                  );
+    DEBUG ((EFI_D_ERROR, "LoadRecoveryCapsule - GetNumberRecoveryCapsules (%d) - %r\n", NumberRecoveryCapsules, Status));
+    if (EFI_ERROR (Status)) {
+      break;
+    }
+    for (CapsuleInstance = 1; CapsuleInstance <= NumberRecoveryCapsules; CapsuleInstance++) {
+      CapsuleSize = 0;
+      Status = DeviceRecoveryPpi->GetRecoveryCapsuleInfo (
+                                    (EFI_PEI_SERVICES **)PeiServices,
+                                    DeviceRecoveryPpi,
+                                    FeaturePcdGet(PcdFrameworkCompatibilitySupport) ? CapsuleInstance - 1 : CapsuleInstance,
+                                    &CapsuleSize,
+                                    &CapsuleType
+                                    );
+      DEBUG ((EFI_D_ERROR, "LoadRecoveryCapsule - GetRecoveryCapsuleInfo (%d - %x) - %r\n", CapsuleInstance, CapsuleSize, Status));
+      if (EFI_ERROR (Status)) {
+        break;
+      }
+
+      CapsuleBuffer = AllocatePages (EFI_SIZE_TO_PAGES(CapsuleSize));
+      if (CapsuleBuffer == NULL) {
+        DEBUG ((EFI_D_ERROR, "LoadRecoveryCapsule - AllocatePool fail\n"));
+        continue;
+      }
+      Status = DeviceRecoveryPpi->LoadRecoveryCapsule (
+                                    (EFI_PEI_SERVICES **)PeiServices,
+                                    DeviceRecoveryPpi,
+                                    FeaturePcdGet(PcdFrameworkCompatibilitySupport) ? CapsuleInstance - 1 : CapsuleInstance,
+                                    CapsuleBuffer
+                                    );
+      DEBUG ((EFI_D_ERROR, "LoadRecoveryCapsule - LoadRecoveryCapsule (%d) - %r\n", CapsuleInstance, Status));
+      if (EFI_ERROR (Status)) {
+        FreePages (CapsuleBuffer, EFI_SIZE_TO_PAGES(CapsuleSize));
+        break;
+      }
+      //
+      // good, load capsule buffer
+      //
+      Status = ProcessRecoveryCapsule (CapsuleBuffer, CapsuleSize);
+      return Status;
+    }
+  }
+
+  return EFI_NOT_FOUND;
+}
diff --git a/MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPei.h b/MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPei.h
new file mode 100644
index 0000000..ce3a35f
--- /dev/null
+++ b/MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPei.h
@@ -0,0 +1,44 @@
+/** @file
+  Recovery module header file.
+
+  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _RECOVERY_MODULE_LOAD_PEI_H_
+#define _RECOVERY_MODULE_LOAD_PEI_H_
+
+#include <PiPei.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+#include <Library/HobLib.h>
+#include <Library/EdkiiSystemCapsuleLib.h>
+
+//
+// Update data
+//
+
+typedef struct {
+  UINTN                           NumOfRecovery;
+} CONFIG_HEADER;
+
+typedef struct {
+  UINTN                           Index;
+  EFI_GUID                        FileGuid;
+  UINTN                           Length;
+  UINTN                           ImageOffset;
+} RECOVERY_CONFIG_DATA;
+
+#endif
+
diff --git a/MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPei.inf b/MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPei.inf
new file mode 100644
index 0000000..2f3bd7a
--- /dev/null
+++ b/MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPei.inf
@@ -0,0 +1,71 @@
+## @file
+# Recovery module.
+#
+# Load Recovery capsule and install FV.
+#
+# Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+#
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution. The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = RecoveryModuleLoadPei
+  MODULE_UNI_FILE                = RecoveryModuleLoadPei.uni
+  FILE_GUID                      = 4278A574-4769-4D60-B090-DD4916691590
+  MODULE_TYPE                    = PEIM
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = InitializeRecoveryModule
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64 IPF EBC
+#
+
+[Sources]
+  RecoveryModuleLoadPei.c
+  ParseConfigProfile.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+  PeimEntryPoint
+  DebugLib
+  HobLib
+  BaseMemoryLib
+  MemoryAllocationLib
+  EdkiiSystemCapsuleLib
+  IniParsingLib
+  PrintLib
+
+[Ppis]
+  gEfiPeiMasterBootModePpiGuid                  # PPI ALWAYS_PRODUCED
+  gEfiPeiBootInRecoveryModePpiGuid              # PPI SOMETIMES_PRODUCED
+  gEfiPeiRecoveryModulePpiGuid
+  gEfiPeiDeviceRecoveryModulePpiGuid
+
+[Guids]
+  gEfiFmpCapsuleGuid                      ## SOMETIMES_CONSUMES ## GUID
+
+[Pcd]
+  gEfiMdeModulePkgTokenSpaceGuid.PcdEdkiiSystemFmpCapsuleImageTypeIdGuid  ## CONSUMES
+
+[FeaturePcd]
+  gEfiMdeModulePkgTokenSpaceGuid.PcdFrameworkCompatibilitySupport         ## CONSUMES
+
+[depex]
+  gEfiPeiBootInRecoveryModePpiGuid
+
+[UserExtensions.TianoCore."ExtraFiles"]
+  RecoveryModuleLoadPeiExtra.uni
+
diff --git a/MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPei.uni b/MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPei.uni
new file mode 100644
index 0000000..44e6cdc
--- /dev/null
+++ b/MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPei.uni
@@ -0,0 +1,21 @@
+// /** @file
+// Recovery module.
+//
+// Load Recovery capsule and install FV.
+//
+// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+//
+// This program and the accompanying materials
+// are licensed and made available under the terms and conditions of the BSD License
+// which accompanies this distribution.  The full text of the license may be found at
+// http://opensource.org/licenses/bsd-license.php
+//
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT             #language en-US "Recovery module."
+
+#string STR_MODULE_DESCRIPTION          #language en-US "Load Recovery capsule and install FV."
diff --git a/MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPeiExtra.uni b/MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPeiExtra.uni
new file mode 100644
index 0000000..56057c6
--- /dev/null
+++ b/MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPeiExtra.uni
@@ -0,0 +1,20 @@
+// /** @file
+// RecoveryModuleLoadPei Localized Strings and Content
+//
+// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+//
+// This program and the accompanying materials
+// are licensed and made available under the terms and conditions of the BSD License
+// which accompanies this distribution.  The full text of the license may be found at
+// http://opensource.org/licenses/bsd-license.php
+//
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+// **/
+
+#string STR_PROPERTIES_MODULE_NAME
+#language en-US
+"RecoveryModuleLoad PEI Driver"
+
+
-- 
2.7.4.windows.1



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

* [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application.
  2016-09-21  6:44 [PATCH 00/45] Add capsule update and recovery sample Jiewen Yao
                   ` (15 preceding siblings ...)
  2016-09-21  6:44 ` [PATCH 16/45] MdeModulePkg/RecoveryModuleLoadPei: Add RecoveryModuleLoadPei Jiewen Yao
@ 2016-09-21  6:44 ` Jiewen Yao
  2016-09-29  1:06   ` Kinney, Michael D
  2016-09-21  6:44 ` [PATCH 18/45] MdeModulePkg/MdeModulePkg.dsc: Add capsule related component Jiewen Yao
                   ` (31 subsequent siblings)
  48 siblings, 1 reply; 83+ messages in thread
From: Jiewen Yao @ 2016-09-21  6:44 UTC (permalink / raw)
  To: edk2-devel; +Cc: Feng Tian, Star Zeng, Michael D Kinney, Liming Gao, Chao Zhang

This CapsuleApp can help perform capsule update in UEFI shell environment.
It can also dump capsule information, capsule status variable, ESRT and FMP.

Cc: Feng Tian <feng.tian@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Chao Zhang <chao.b.zhang@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
---
 MdeModulePkg/Application/CapsuleApp/AppSupport.c        |  480 +++++++++
 MdeModulePkg/Application/CapsuleApp/CapsuleApp.c        | 1047 ++++++++++++++++++++
 MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf      |   71 ++
 MdeModulePkg/Application/CapsuleApp/CapsuleApp.uni      |   22 +
 MdeModulePkg/Application/CapsuleApp/CapsuleAppExtra.uni |   19 +
 MdeModulePkg/Application/CapsuleApp/CapsuleDump.c       |  840 ++++++++++++++++
 6 files changed, 2479 insertions(+)

diff --git a/MdeModulePkg/Application/CapsuleApp/AppSupport.c b/MdeModulePkg/Application/CapsuleApp/AppSupport.c
new file mode 100644
index 0000000..365067d
--- /dev/null
+++ b/MdeModulePkg/Application/CapsuleApp/AppSupport.c
@@ -0,0 +1,480 @@
+/** @file
+  A shell application that triggers capsule update process.
+
+  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Uefi.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/UefiLib.h>
+#include <Library/PrintLib.h>
+#include <Protocol/LoadedImage.h>
+#include <Protocol/SimpleFileSystem.h>
+#include <Guid/FileInfo.h>
+#include <Guid/Gpt.h>
+
+#define MAX_ARG_NUM     11
+
+UINTN  Argc = 0;
+CHAR16 *Argv[MAX_ARG_NUM];
+CHAR16 *ArgBuffer;
+
+/**
+
+  This function parse application ARG.
+
+  @return Status
+**/
+EFI_STATUS
+GetArg (
+  VOID
+  )
+{
+  UINT8                         *Data;
+  UINTN                         DataSize;
+  CHAR16                        *Index;
+  CHAR16                        *End;
+  CHAR16                        *DIndex;
+  EFI_STATUS                    Status;
+  EFI_LOADED_IMAGE_PROTOCOL     *LoadedImage;
+
+  Status = gBS->HandleProtocol (
+                  gImageHandle,
+                  &gEfiLoadedImageProtocolGuid,
+                  (VOID**)&LoadedImage
+                  );
+  if (EFI_ERROR(Status)) {
+    return Status;
+  }
+
+  Data = LoadedImage->LoadOptions;
+  DataSize = LoadedImage->LoadOptionsSize;
+
+  End = (CHAR16*)(UINTN)(Data + DataSize);
+  Status = gBS->AllocatePool (EfiBootServicesData, DataSize, (VOID **)&ArgBuffer);
+  ASSERT_EFI_ERROR (Status);
+  DIndex = ArgBuffer;
+  Argv[Argc++] = ArgBuffer;
+  for (Index = (CHAR16*)Data; Index < End; ) {
+    if (*Index == L' ') {
+      *DIndex = L'\0';
+      if (Argc >= MAX_ARG_NUM) {
+        return EFI_UNSUPPORTED;
+      }
+      Argv[Argc++] = (++ DIndex);
+      while(*Index == L' ') {
+        Index ++;
+      }
+    }
+    (*(DIndex ++)) = (*(Index ++));
+  }
+  return EFI_SUCCESS;
+}
+
+/**
+  Clear APP ARG.
+**/
+VOID
+CleanArg (
+  VOID
+  )
+{
+  FreePool (Argv[0]);
+}
+
+/**
+  Return File System Volume containing this shell application.
+
+  @return File System Volume containing this shell application.
+**/
+EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *
+GetMyVol (
+  VOID
+  )
+{
+  EFI_STATUS                        Status;
+  EFI_LOADED_IMAGE_PROTOCOL         *LoadedImage;
+  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Vol;
+
+  Status = gBS->HandleProtocol (
+                  gImageHandle,
+                  &gEfiLoadedImageProtocolGuid,
+                  (VOID **)&LoadedImage
+                  );
+  ASSERT_EFI_ERROR (Status);
+
+  Status = gBS->HandleProtocol (
+                  LoadedImage->DeviceHandle,
+                  &gEfiSimpleFileSystemProtocolGuid,
+                  (VOID **)&Vol
+                  );
+  if (!EFI_ERROR (Status)) {
+    return Vol;
+  }
+
+  return NULL;
+}
+
+/**
+  Read a file from this volume.
+
+  @param Vol             File System Volume
+  @param FileName        The file to be read.
+  @param BufferSize      The file buffer size
+  @param Buffer          The file buffer
+
+  @retval EFI_SUCCESS    Read file successfully
+  @retval EFI_NOT_FOUND  File not found
+**/
+EFI_STATUS
+ReadFileFromVol (
+  IN  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Vol,
+  IN  CHAR16                            *FileName,
+  OUT UINTN                             *BufferSize,
+  OUT VOID                              **Buffer
+  )
+{
+  EFI_STATUS                        Status;
+  EFI_FILE_HANDLE                   RootDir;
+  EFI_FILE_HANDLE                   Handle;
+  UINTN                             FileInfoSize;
+  EFI_FILE_INFO                     *FileInfo;
+  UINTN                             TempBufferSize;
+  VOID                              *TempBuffer;
+
+  //
+  // Open the root directory
+  //
+  Status = Vol->OpenVolume (Vol, &RootDir);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Open the file
+  //
+  Status = RootDir->Open (
+                      RootDir,
+                      &Handle,
+                      FileName,
+                      EFI_FILE_MODE_READ,
+                      0
+                      );
+  if (EFI_ERROR (Status)) {
+    RootDir->Close (RootDir);
+    return Status;
+  }
+
+  RootDir->Close (RootDir);
+
+  //
+  // Get the file information
+  //
+  FileInfoSize = sizeof(EFI_FILE_INFO) + 1024;
+
+  FileInfo = AllocateZeroPool (FileInfoSize);
+  if (FileInfo == NULL) {
+    Handle->Close (Handle);
+    return Status;
+  }
+
+  Status = Handle->GetInfo (
+                     Handle,
+                     &gEfiFileInfoGuid,
+                     &FileInfoSize,
+                     FileInfo
+                     );
+  if (EFI_ERROR (Status)) {
+    Handle->Close (Handle);
+    gBS->FreePool (FileInfo);
+    return Status;
+  }
+
+  //
+  // Allocate buffer for the file data. The last CHAR16 is for L'\0'
+  //
+  TempBufferSize = (UINTN) FileInfo->FileSize + sizeof(CHAR16);
+  TempBuffer = AllocateZeroPool (TempBufferSize);
+  if (TempBuffer == NULL) {
+    Handle->Close (Handle);
+    gBS->FreePool (FileInfo);
+    return Status;
+  }
+
+  gBS->FreePool (FileInfo);
+
+  //
+  // Read the file data to the buffer
+  //
+  Status = Handle->Read (
+                     Handle,
+                     &TempBufferSize,
+                     TempBuffer
+                     );
+  if (EFI_ERROR (Status)) {
+    Handle->Close (Handle);
+    gBS->FreePool (TempBuffer);
+    return Status;
+  }
+
+  Handle->Close (Handle);
+
+  *BufferSize = TempBufferSize;
+  *Buffer     = TempBuffer;
+  return EFI_SUCCESS;
+}
+
+/**
+  Read a file.
+  If ScanFs is FLASE, it will use this Vol as default Fs.
+  If ScanFs is TRUE, it will scan all FS and check the file.
+    If there is only one file match the name, it will be read.
+    If there is more than one file match the name, it will return Error.
+
+  @param ThisVol         File System Volume
+  @param FileName        The file to be read.
+  @param BufferSize      The file buffer size
+  @param Buffer          The file buffer
+  @param ScanFs          Need Scan all FS
+
+  @retval EFI_SUCCESS    Read file successfully
+  @retval EFI_NOT_FOUND  File not found
+  @retval EFI_NO_MAPPING There is duplicated files found
+**/
+EFI_STATUS
+ReadFileToBufferEx (
+  IN OUT EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   **ThisVol,
+  IN  CHAR16                               *FileName,
+  OUT UINTN                                *BufferSize,
+  OUT VOID                                 **Buffer,
+  IN  BOOLEAN                              ScanFs
+  )
+{
+  EFI_STATUS                        Status;
+  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Vol;
+  UINTN                             TempBufferSize;
+  VOID                              *TempBuffer;
+  UINTN                             NoHandles;
+  EFI_HANDLE                        *HandleBuffer;
+  UINTN                             Index;
+
+  //
+  // Check parameters
+  //
+  if ((FileName == NULL) || (Buffer == NULL) || (ThisVol == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // not scan fs
+  //
+  if (!ScanFs) {
+    if (*ThisVol == NULL) {
+      *ThisVol = GetMyVol ();
+      if (*ThisVol == NULL) {
+        return EFI_INVALID_PARAMETER;
+      }
+    }
+    //
+    // Read file directly from Vol
+    //
+    return ReadFileFromVol (*ThisVol, FileName, BufferSize, Buffer);
+  }
+
+  //
+  // need scan fs
+  //
+
+  //
+  // Get all Vol handle
+  //
+  Status = gBS->LocateHandleBuffer (
+                   ByProtocol,
+                   &gEfiSimpleFileSystemProtocolGuid,
+                   NULL,
+                   &NoHandles,
+                   &HandleBuffer
+                   );
+  if (EFI_ERROR (Status) && (NoHandles == 0)) {
+    return EFI_NOT_FOUND;
+  }
+
+  //
+  // Walk through each Vol
+  //
+  *ThisVol = NULL;
+  *BufferSize = 0;
+  *Buffer     = NULL;
+  for (Index = 0; Index < NoHandles; Index++) {
+    Status = gBS->HandleProtocol (
+                    HandleBuffer[Index],
+                    &gEfiSimpleFileSystemProtocolGuid,
+                    (VOID **)&Vol
+                    );
+    if (EFI_ERROR(Status)) {
+      continue;
+    }
+
+    Status = ReadFileFromVol (Vol, FileName, &TempBufferSize, &TempBuffer);
+    if (!EFI_ERROR (Status)) {
+      //
+      // Read file OK, check duplication
+      //
+      if (*ThisVol != NULL) {
+        //
+        // Find the duplicated file
+        //
+        gBS->FreePool (TempBuffer);
+        gBS->FreePool (*Buffer);
+        Print (L"Duplicated FileName found!\n");
+        return EFI_NO_MAPPING;
+      } else {
+        //
+        // Record value
+        //
+        *ThisVol = Vol;
+        *BufferSize = TempBufferSize;
+        *Buffer     = TempBuffer;
+      }
+    }
+  }
+
+  //
+  // Scan Fs done
+  //
+  if (*ThisVol == NULL) {
+    return EFI_NOT_FOUND;
+  }
+
+  //
+  // Done
+  //
+  return EFI_SUCCESS;
+}
+
+/**
+  Read a file.
+
+  @param FileName        The file to be read.
+  @param BufferSize      The file buffer size
+  @param Buffer          The file buffer
+
+  @retval EFI_SUCCESS    Read file successfully
+  @retval EFI_NOT_FOUND  File not found
+**/
+EFI_STATUS
+ReadFileToBuffer (
+  IN  CHAR16                               *FileName,
+  OUT UINTN                                *BufferSize,
+  OUT VOID                                 **Buffer
+  )
+{
+  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Vol;
+  Vol = NULL;
+  return ReadFileToBufferEx(&Vol, FileName, BufferSize, Buffer, FALSE);
+}
+
+/**
+  Write a file.
+
+  @param FileName        The file to be written.
+  @param BufferSize      The file buffer size
+  @param Buffer          The file buffer
+
+  @retval EFI_SUCCESS    Write file successfully
+**/
+EFI_STATUS
+WriteFileFromBuffer(
+  IN  CHAR16                               *FileName,
+  IN  UINTN                                BufferSize,
+  IN  VOID                                 *Buffer
+  )
+{
+  EFI_STATUS                        Status;
+  EFI_FILE_HANDLE                   RootDir;
+  EFI_FILE_HANDLE                   Handle;
+  UINTN                             TempBufferSize;
+  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Vol;
+
+  Vol = GetMyVol();
+
+  //
+  // Open the root directory
+  //
+  Status = Vol->OpenVolume (Vol, &RootDir);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Open the file
+  //
+  Status = RootDir->Open (
+                      RootDir,
+                      &Handle,
+                      FileName,
+                      EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE| EFI_FILE_MODE_CREATE,
+                      0
+                      );
+  if (EFI_ERROR (Status)) {
+    RootDir->Close (RootDir);
+    return Status;
+  }
+
+  //
+  // Delete file
+  //
+  Status = Handle->Delete(Handle);
+  if (EFI_ERROR(Status)) {
+    return Status;
+  }
+
+  //
+  // Open the file again
+  //
+  Status = RootDir->Open (
+                      RootDir,
+                      &Handle,
+                      FileName,
+                      EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE| EFI_FILE_MODE_CREATE,
+                      0
+                      );
+  if (EFI_ERROR (Status)) {
+    RootDir->Close (RootDir);
+    return Status;
+  }
+
+  RootDir->Close (RootDir);
+
+  //
+  // Write the file data from the buffer
+  //
+  TempBufferSize = BufferSize;
+  Status = Handle->Write (
+                     Handle,
+                     &TempBufferSize,
+                     Buffer
+                     );
+  if (EFI_ERROR (Status)) {
+    Handle->Close (Handle);
+    return Status;
+  }
+
+  Handle->Close (Handle);
+
+  return EFI_SUCCESS;
+}
+
diff --git a/MdeModulePkg/Application/CapsuleApp/CapsuleApp.c b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.c
new file mode 100644
index 0000000..0a28557
--- /dev/null
+++ b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.c
@@ -0,0 +1,1047 @@
+/** @file
+  A shell application that triggers capsule update process.
+
+  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Uefi.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/UefiLib.h>
+#include <Library/PrintLib.h>
+#include <Protocol/LoadedImage.h>
+#include <Protocol/SimpleFileSystem.h>
+#include <Protocol/GraphicsOutput.h>
+#include <Guid/FileInfo.h>
+#include <Guid/Gpt.h>
+#include <Guid/GlobalVariable.h>
+#include <Guid/CapsuleReport.h>
+#include <Guid/SystemResourceTable.h>
+#include <Guid/FmpCapsule.h>
+#include <IndustryStandard/WindowsUxCapsule.h>
+
+#define CAPSULE_HEADER_SIZE  0x20
+
+#define NESTED_CAPSULE_HEADER_SIZE  SIZE_4KB
+#define SYSTEM_FIRMWARE_FLAG 0x50000
+#define DEVICE_FIRMWARE_FLAG 0x78010
+
+#define EFI_CAPSULE_FROM_FILE_DIR                           L"\\EFI\\UpdateCapsule\\"
+#define EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED  0x0000000000000004
+
+#define MAJOR_VERSION   1
+#define MINOR_VERSION   0
+
+#define MAX_ARG_NUM     11
+#define MAX_CAPSULE_NUM (MAX_ARG_NUM - 1)
+
+extern UINTN  Argc;
+extern CHAR16 *Argv[];
+
+//
+// Define how many block descriptors we want to test with.
+//
+UINTN  NumberOfDescriptors = 1;
+UINTN  CapsuleFirstIndex;
+UINTN  CapsuleLastIndex;
+
+/**
+  Dump capsule information
+
+  @retval EFI_SUCCESS            The capsule information is dumped.
+  @retval EFI_UNSUPPORTED        Input parameter is not valid.
+**/
+EFI_STATUS
+DumpCapsule(
+  VOID
+  );
+
+/**
+  Dump capsule status variable.
+
+  @retval EFI_SUCCESS            The capsule status variable is dumped.
+  @retval EFI_UNSUPPORTED        Input parameter is not valid.
+**/
+EFI_STATUS
+DmpCapsuleStatusVariable(
+  VOID
+  );
+
+/**
+  Dump FMP protocol info.
+**/
+VOID
+DumpFmpData(
+  VOID
+  );
+
+/**
+  Dump ESRT info.
+**/
+VOID
+DumpEsrtData(
+  VOID
+  );
+
+/**
+  Read a file.
+
+  @param FileName        The file to be read.
+  @param BufferSize      The file buffer size
+  @param Buffer          The file buffer
+
+  @retval EFI_SUCCESS    Read file successfully
+  @retval EFI_NOT_FOUND  File not found
+**/
+EFI_STATUS
+ReadFileToBuffer(
+  IN  CHAR16                               *FileName,
+  OUT UINTN                                *BufferSize,
+  OUT VOID                                 **Buffer
+  );
+
+/**
+  Write a file.
+
+  @param FileName        The file to be written.
+  @param BufferSize      The file buffer size
+  @param Buffer          The file buffer
+
+  @retval EFI_SUCCESS    Write file successfully
+**/
+EFI_STATUS
+WriteFileFromBuffer(
+  IN  CHAR16                               *FileName,
+  IN  UINTN                                BufferSize,
+  IN  VOID                                 *Buffer
+  );
+
+/**
+
+  This function parse application ARG.
+
+  @return Status
+**/
+EFI_STATUS
+GetArg (
+  VOID
+  );
+
+/**
+  Clear APP ARG.
+**/
+VOID
+CleanArg (
+  VOID
+  );
+
+/**
+  Create UX capsule.
+
+  @retval EFI_SUCCESS            The capsule header is appended.
+  @retval EFI_UNSUPPORTED        Input parameter is not valid.
+  @retval EFI_OUT_OF_RESOURCES   No enough resource to create UX capsule.
+**/
+EFI_STATUS
+CreateBmpFmp(
+  VOID
+  )
+{
+  CHAR16                                        *OutputCapsuleName;
+  VOID                                          *BmpBuffer;
+  UINTN                                         FileSize;
+  CHAR16                                        *BmpName;
+  UINT8                                         *FullCapsuleBuffer;
+  UINTN                                         FullCapsuleBufferSize;
+  EFI_DISPLAY_CAPSULE                           *DisplayCapsule;
+  EFI_STATUS                                    Status;
+  EFI_GRAPHICS_OUTPUT_PROTOCOL                  *Gop;
+
+  Status = gBS->LocateProtocol(&gEfiGraphicsOutputProtocolGuid, NULL, (VOID **)&Gop);
+  if (EFI_ERROR(Status)) {
+    Print(L"CapsuleApp: NO GOP is found.\n");
+    return EFI_UNSUPPORTED;
+  }
+  Print(L"Current GOP: Mode - %d, ", Gop->Mode->Mode);
+  Print(L"HorizontalResolution - %d, ", Gop->Mode->Info->HorizontalResolution);
+  Print(L"VerticalResolution - %d\n", Gop->Mode->Info->VerticalResolution);
+  // HorizontalResolution >= BMP_IMAGE_HEADER.PixelWidth
+  // VerticalResolution   >= BMP_IMAGE_HEADER.PixelHeight
+
+  if (Argc != 5) {
+    Print(L"CapsuleApp: Invalid Parameter.\n");
+    return EFI_UNSUPPORTED;
+  }
+
+  if (StrCmp(Argv[3], L"-O") != 0) {
+    Print(L"CapsuleApp: NO output capsule name.\n");
+    return EFI_UNSUPPORTED;
+  }
+  OutputCapsuleName = Argv[4];
+
+  BmpBuffer = NULL;
+  FileSize = 0;
+  FullCapsuleBuffer = NULL;
+
+  BmpName = Argv[2];
+  Status = ReadFileToBuffer(BmpName, &FileSize, &BmpBuffer);
+  if (EFI_ERROR(Status)) {
+    Print(L"CapsuleApp: BMP image (%s) is not found.\n", BmpName);
+    goto Done;
+  }
+
+  FullCapsuleBufferSize = sizeof(EFI_DISPLAY_CAPSULE) + FileSize;
+  FullCapsuleBuffer = AllocatePool(FullCapsuleBufferSize);
+  if (FullCapsuleBuffer == NULL) {
+    Print(L"CapsuleApp: Capsule Buffer size (0x%x) too big.\n", FullCapsuleBufferSize);
+    Status = EFI_OUT_OF_RESOURCES;
+    goto Done;
+  }
+
+  DisplayCapsule = (EFI_DISPLAY_CAPSULE *)FullCapsuleBuffer;
+  CopyGuid(&DisplayCapsule->CapsuleHeader.CapsuleGuid, &gWindowsUxCapsuleGuid);
+  DisplayCapsule->CapsuleHeader.HeaderSize = sizeof(DisplayCapsule->CapsuleHeader);
+  DisplayCapsule->CapsuleHeader.Flags = CAPSULE_FLAGS_PERSIST_ACROSS_RESET;
+  DisplayCapsule->CapsuleHeader.CapsuleImageSize = (UINT32)FullCapsuleBufferSize;
+
+  DisplayCapsule->ImagePayload.Version = 1;
+  DisplayCapsule->ImagePayload.Checksum = 0;
+  DisplayCapsule->ImagePayload.ImageType = 0; // BMP
+  DisplayCapsule->ImagePayload.Reserved = 0;
+  DisplayCapsule->ImagePayload.Mode = Gop->Mode->Mode;
+  DisplayCapsule->ImagePayload.OffsetX = 0;
+  DisplayCapsule->ImagePayload.OffsetY = 0;
+
+  CopyMem((DisplayCapsule + 1), BmpBuffer, FileSize);
+
+  DisplayCapsule->ImagePayload.Checksum = CalculateCheckSum8(FullCapsuleBuffer, FullCapsuleBufferSize);
+
+  Status = WriteFileFromBuffer(OutputCapsuleName, FullCapsuleBufferSize, FullCapsuleBuffer);
+  Print(L"CapsuleApp: Write %s %r\n", OutputCapsuleName, Status);
+
+Done:
+  if (BmpBuffer != NULL) {
+    FreePool(BmpBuffer);
+  }
+
+  if (FullCapsuleBuffer != NULL) {
+    FreePool(FullCapsuleBuffer);
+  }
+
+  return Status;
+}
+
+/**
+  Get ImageTypeId in the FMP capsule header.
+
+  @param CapsuleHeader  The FMP capsule image header.
+
+  @return ImageTypeId
+**/
+EFI_GUID *
+GetCapsuleImageTypeId(
+  IN EFI_CAPSULE_HEADER                            *CapsuleHeader
+  )
+{
+  EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER       *FmpCapsuleHeader;
+  UINT64                                       *ItemOffsetList;
+  EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader;
+
+  FmpCapsuleHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *)((UINT8 *)CapsuleHeader + CapsuleHeader->HeaderSize);
+  ItemOffsetList = (UINT64 *)(FmpCapsuleHeader + 1);
+  if (FmpCapsuleHeader->PayloadItemCount == 0) {
+    return NULL;
+  }
+  ImageHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *)((UINT8 *)FmpCapsuleHeader + ItemOffsetList[FmpCapsuleHeader->EmbeddedDriverCount]);
+  return &ImageHeader->UpdateImageTypeId;
+}
+
+/**
+  Get ESRT FwType according to ImageTypeId
+
+  @param  ImageTypeId   ImageTypeId of an FMP capsule.
+
+  @return ESRT FwType
+**/
+UINT32
+GetEsrtFwType(
+  IN  EFI_GUID                                      *ImageTypeId
+  )
+{
+  EFI_STATUS                 Status;
+  EFI_SYSTEM_RESOURCE_TABLE  *Esrt;
+  EFI_SYSTEM_RESOURCE_ENTRY  *EsrtEntry;
+  UINTN                      Index;
+
+  //
+  // Check ESRT
+  //
+  Status = EfiGetSystemConfigurationTable(&gEfiSystemResourceTableGuid, (VOID **)&Esrt);
+  if (!EFI_ERROR(Status)) {
+    EsrtEntry = (VOID *)(Esrt + 1);
+    for (Index = 0; Index < Esrt->FwResourceCount; Index++, EsrtEntry++) {
+      if (CompareGuid(&EsrtEntry->FwClass, ImageTypeId)) {
+        return EsrtEntry->FwType;
+      }
+    }
+  }
+
+  return ESRT_FW_TYPE_UNKNOWN;
+}
+
+/**
+  Append a capsule header on top of current image.
+  This function follows Windows UEFI Firmware Update Platform document.
+
+  @retval EFI_SUCCESS            The capsule header is appended.
+  @retval EFI_UNSUPPORTED        Input parameter is not valid.
+  @retval EFI_OUT_OF_RESOURCES   No enough resource to append capsule header.
+**/
+EFI_STATUS
+CreateNestedFmp(
+  VOID
+  )
+{
+  CHAR16                                        *OutputCapsuleName;
+  VOID                                          *CapsuleBuffer;
+  UINTN                                         FileSize;
+  CHAR16                                        *CapsuleName;
+  UINT8                                         *FullCapsuleBuffer;
+  UINTN                                         FullCapsuleBufferSize;
+  EFI_CAPSULE_HEADER                            *NestedCapsuleHeader;
+  EFI_GUID                                      *ImageTypeId;
+  UINT32                                        FwType;
+  EFI_STATUS                                    Status;
+
+  if (Argc != 5) {
+    Print(L"CapsuleApp: Invalid Parameter.\n");
+    return EFI_UNSUPPORTED;
+  }
+
+  if (StrCmp(Argv[3], L"-O") != 0) {
+    Print(L"CapsuleApp: NO output capsule name.\n");
+    return EFI_UNSUPPORTED;
+  }
+  OutputCapsuleName = Argv[4];
+
+  CapsuleBuffer = NULL;
+  FileSize = 0;
+  FullCapsuleBuffer = NULL;
+
+  CapsuleName = Argv[2];
+  Status = ReadFileToBuffer(CapsuleName, &FileSize, &CapsuleBuffer);
+  if (EFI_ERROR(Status)) {
+    Print(L"CapsuleApp: Capsule image (%s) is not found.\n", CapsuleName);
+    goto Done;
+  }
+
+  ImageTypeId = GetCapsuleImageTypeId(CapsuleBuffer);
+  if (ImageTypeId == NULL) {
+    Print(L"CapsuleApp: Capsule ImageTypeId is not found.\n");
+    goto Done;
+  }
+  FwType = GetEsrtFwType(ImageTypeId);
+  if ((FwType != ESRT_FW_TYPE_SYSTEMFIRMWARE) && (FwType != ESRT_FW_TYPE_DEVICEFIRMWARE)) {
+    Print(L"CapsuleApp: Capsule FwType is invalid.\n");
+    goto Done;
+  }
+
+  FullCapsuleBufferSize = NESTED_CAPSULE_HEADER_SIZE + FileSize;
+  FullCapsuleBuffer = AllocatePool(FullCapsuleBufferSize);
+  if (FullCapsuleBuffer == NULL) {
+    Print(L"CapsuleApp: Capsule Buffer size (0x%x) too big.\n", FullCapsuleBufferSize);
+    Status = EFI_OUT_OF_RESOURCES;
+    goto Done;
+  }
+
+  NestedCapsuleHeader = (EFI_CAPSULE_HEADER *)FullCapsuleBuffer;
+  ZeroMem(NestedCapsuleHeader, NESTED_CAPSULE_HEADER_SIZE);
+  CopyGuid(&NestedCapsuleHeader->CapsuleGuid, ImageTypeId);
+  NestedCapsuleHeader->HeaderSize = NESTED_CAPSULE_HEADER_SIZE;
+  NestedCapsuleHeader->Flags = (FwType == ESRT_FW_TYPE_DEVICEFIRMWARE) ? SYSTEM_FIRMWARE_FLAG : DEVICE_FIRMWARE_FLAG;
+  NestedCapsuleHeader->CapsuleImageSize = (UINT32)FullCapsuleBufferSize;
+
+  CopyMem((UINT8 *)NestedCapsuleHeader + NestedCapsuleHeader->HeaderSize, CapsuleBuffer, FileSize);
+
+  Status = WriteFileFromBuffer(OutputCapsuleName, FullCapsuleBufferSize, FullCapsuleBuffer);
+  Print(L"CapsuleApp: Write %s %r\n", OutputCapsuleName, Status);
+
+Done:
+  if (CapsuleBuffer != NULL) {
+    FreePool(CapsuleBuffer);
+  }
+
+  if (FullCapsuleBuffer != NULL) {
+    FreePool(FullCapsuleBuffer);
+  }
+
+  return Status;
+}
+
+
+/**
+  Clear capsule status variable.
+
+  @retval EFI_SUCCESS            The capsule status variable is cleared.
+**/
+EFI_STATUS
+ClearCapsuleStatusVariable(
+  VOID
+  )
+{
+  EFI_STATUS                          Status;
+  UINT32                              Index;
+  CHAR16                              CapsuleVarName[20];
+  CHAR16                              *TempVarName;
+
+  StrCpyS (CapsuleVarName, sizeof(CapsuleVarName)/sizeof(CapsuleVarName[0]), L"Capsule");
+  TempVarName = CapsuleVarName + StrLen (CapsuleVarName);
+  Index = 0;
+
+  while (TRUE) {
+    UnicodeSPrint (TempVarName, 5 * sizeof(CHAR16), L"%04x", Index);
+
+    Status = gRT->SetVariable (
+                    CapsuleVarName,
+                    &gEfiCapsuleReportGuid,
+                    EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS,
+                    0,
+                    (VOID *)NULL
+                    );
+    if (EFI_ERROR(Status)) {
+      //
+      // There is no capsule variables, quit
+      //
+      break;
+    }
+
+    Index++;
+    if (Index > 0xFFFF) {
+      break;
+    }
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Get the active UEFI system partition from bootoption list.
+
+  @param[out] Fs    Simple File System protocol on the active UEFI system partition
+
+  @retval EFI_SUCCESS   active UEFI system partition found
+**/
+EFI_STATUS
+GetEfiSysPartition(
+  OUT EFI_SIMPLE_FILE_SYSTEM_PROTOCOL **Fs
+  )
+{
+  EFI_STATUS                       Status;
+  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL  *FsTemp;
+  UINTN                            NoHandles;
+  EFI_HANDLE                       *Handles;
+  UINTN                            Index;
+
+  Handles = NULL;
+
+  //
+  // search for EFI system partition protocol on Boot option device path
+  //
+  Status = gBS->LocateHandleBuffer(ByProtocol, &gEfiPartTypeSystemPartGuid, NULL, &NoHandles, &Handles);
+  if (EFI_ERROR(Status)) {
+    return Status;
+  }
+
+  //
+  // Skip BootOptions within FV
+  //
+  for (Index = 0; Index < NoHandles; Index++) {
+    Status = gBS->HandleProtocol (Handles[Index], &gEfiSimpleFileSystemProtocolGuid, (VOID **)&FsTemp);
+    if (!EFI_ERROR (Status)){
+      *Fs = FsTemp;
+      break;
+    }
+  }
+  return Status;
+}
+
+/**
+  Copy a list of capsule images to the active UEFI system partition from bootoption list.
+
+  @param[in] CapsuleBuffer    An array of pointer to capsule images
+  @param[in] FileSize         An array of UINTN to capsule images size
+  @param[in] CapsuleNum       The count of capsule images
+
+  @retval EFI_SUCCESS   Capsule images are copied to the active UEFI system partition
+**/
+EFI_STATUS
+CopyCapsuleToActiveEfiPartition(
+  IN VOID                          **CapsuleBuffer,
+  IN UINTN                         *FileSize,
+  IN UINTN                         CapsuleNum
+  )
+{
+  EFI_STATUS                       Status;
+  CHAR16                           *CapsuleName;
+  UINTN                            Index;
+  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL  *Fs;
+  EFI_FILE_HANDLE                  RootDir;
+  EFI_FILE_HANDLE                  CapsuleDir;
+  EFI_FILE_HANDLE                  DestHandle;
+  UINTN                            DataSize;
+  UINT64                           OsIndication;
+
+  RootDir      = NULL;
+  CapsuleDir   = NULL;
+
+  Status = GetEfiSysPartition(&Fs);
+  if (EFI_ERROR(Status)) {
+    Print (L"Can not find active UEFI System Partition\n");
+    return Status;
+  }
+
+  Status = Fs->OpenVolume(Fs, &RootDir);
+  if (EFI_ERROR(Status)) {
+    goto EXIT;
+  }
+
+  Status = RootDir->Open(
+                      RootDir,
+                      &CapsuleDir,
+                      EFI_CAPSULE_FROM_FILE_DIR,
+                      EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE,
+                      EFI_FILE_DIRECTORY
+                      );
+  if (EFI_ERROR(Status)) {
+    goto EXIT;
+  }
+
+  //
+  // Read the input files.
+  //
+  for (Index = 0; Index < CapsuleNum; Index++) {
+    CapsuleName = Argv[CapsuleFirstIndex + Index];
+    Status = CapsuleDir->Open(
+                           CapsuleDir,
+                           &DestHandle,
+                           CapsuleName,
+                           EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE,
+                           EFI_FILE_ARCHIVE
+                           );
+    if (EFI_ERROR(Status)) {
+      Print(L"CapsuleApp: %s open error - %r\n", CapsuleName, Status);
+      continue;
+    }
+
+    DataSize = FileSize[Index];
+    Status = DestHandle->Write(
+                           DestHandle,
+                           &DataSize,
+                           CapsuleBuffer[Index]
+                           );
+    DestHandle->Close(DestHandle);
+    if (EFI_ERROR(Status)) {
+      Print(L"CapsuleApp: %s write error - %r, FileSize - 0x%x\n", CapsuleName, Status, FileSize[Index]);
+    }
+  }
+
+  Status = gRT->GetVariable (
+                  L"OsIndications",
+                  &gEfiGlobalVariableGuid,
+                  NULL,
+                  &DataSize,
+                  (VOID *) &OsIndication
+                  );
+
+  if (EFI_ERROR(Status) || DataSize != sizeof(OsIndication)) {
+    OsIndication = 0;
+  }
+
+  //
+  // Set OsIndications Variable EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED bit
+  //
+  OsIndication |= EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED;
+  Status = gRT->SetVariable (
+                  L"OsIndications",
+                  &gEfiGlobalVariableGuid,
+                  EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS |
+                  EFI_VARIABLE_BOOTSERVICE_ACCESS,
+                  sizeof(OsIndication),
+                  (VOID *)&OsIndication
+                  );
+
+
+EXIT:
+  if (RootDir != NULL) {
+    RootDir->Close(RootDir);
+  }
+
+  if (CapsuleDir != NULL) {
+    CapsuleDir->Close(CapsuleDir);
+  }
+
+  return Status;
+}
+
+/**
+  Build Gather list for a list of capsule images.
+
+  @param[in]  CapsuleBuffer    An array of pointer to capsule images
+  @param[in]  FileSize         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                         *FileSize,
+  IN UINTN                         CapsuleNum,
+  OUT EFI_CAPSULE_BLOCK_DESCRIPTOR **BlockDescriptors
+  )
+{
+  EFI_STATUS                    Status;
+  EFI_CAPSULE_BLOCK_DESCRIPTOR  *BlockDescriptors1;
+  EFI_CAPSULE_BLOCK_DESCRIPTOR  *BlockDescriptors2;
+  EFI_CAPSULE_BLOCK_DESCRIPTOR  *BlockDescriptorPre;
+  EFI_CAPSULE_BLOCK_DESCRIPTOR  *BlockDescriptorsHeader;
+  EFI_CAPSULE_BLOCK_DESCRIPTOR  *TempBlockPtr;
+  UINT8                         *TempDataPtr;
+  UINTN                         SizeLeft;
+  UINTN                         Size;
+  INT32                         Count;
+  INT32                         Number;
+  UINTN                         Index;
+
+  TempBlockPtr           = NULL;
+  BlockDescriptors1      = NULL;
+  BlockDescriptors2      = NULL;
+  BlockDescriptorPre     = NULL;
+  BlockDescriptorsHeader = NULL;
+
+  for (Index = 0; Index < CapsuleNum; Index++) {
+    //
+    // Allocate memory for the descriptors.
+    //
+    if (NumberOfDescriptors == 1) {
+      Count = 2;
+    } else {
+      Count = (INT32)(NumberOfDescriptors + 2) / 2;
+    }
+
+    Size               = Count * sizeof (EFI_CAPSULE_BLOCK_DESCRIPTOR);
+    BlockDescriptors1  = AllocateRuntimeZeroPool (Size);
+    if (BlockDescriptors1 == NULL) {
+      Print (L"CapsuleApp: failed to allocate memory for descriptors\n");
+      Status = EFI_OUT_OF_RESOURCES;
+      goto ERREXIT;
+    } else {
+      Print (L"CapsuleApp: creating capsule descriptors at 0x%X\n", (UINTN) BlockDescriptors1);
+      Print (L"CapsuleApp: capsule data starts          at 0x%X with size 0x%X\n", (UINTN) CapsuleBuffer, FileSize);
+    }
+
+    //
+    // Record descirptor header
+    //
+    if (Index == 0) {
+      BlockDescriptorsHeader = BlockDescriptors1;
+    }
+
+    if (BlockDescriptorPre != NULL) {
+      BlockDescriptorPre->Union.ContinuationPointer = (UINTN) BlockDescriptors1;
+      BlockDescriptorPre->Length = 0;
+    }
+
+    //
+    // Fill them in
+    //
+    TempBlockPtr  = BlockDescriptors1;
+    TempDataPtr   = CapsuleBuffer[Index];
+    SizeLeft      = FileSize[Index];
+    for (Number = 0; (Number < Count - 1) && (SizeLeft != 0); Number++) {
+      //
+      // Divide remaining data in half
+      //
+      if (NumberOfDescriptors != 1) {
+        if (SizeLeft == 1) {
+          Size = 1;
+        } else {
+          Size = SizeLeft / 2;
+        }
+      } else {
+        Size = SizeLeft;
+      }
+      TempBlockPtr->Union.DataBlock    = (UINTN)TempDataPtr;
+      TempBlockPtr->Length  = Size;
+      Print (L"CapsuleApp: capsule block/size              0x%X/0x%X\n", (UINTN) TempDataPtr, Size);
+      SizeLeft -= Size;
+      TempDataPtr += Size;
+      TempBlockPtr++;
+    }
+
+    //
+    // Allocate the second list, point the first block's last entry to point
+    // to this one, and fill this one in. Worst case is that the previous
+    // list only had one element that pointed here, so we need at least two
+    // elements -- one to point to all the data, another to terminate the list.
+    //
+    if ((NumberOfDescriptors != 1) && (SizeLeft != 0)) {
+      Count = (INT32)(NumberOfDescriptors + 2) - Count;
+      if (Count == 1) {
+        Count++;
+      }
+
+      Size              = Count * sizeof (EFI_CAPSULE_BLOCK_DESCRIPTOR);
+      BlockDescriptors2 = AllocateRuntimeZeroPool (Size);
+      if (BlockDescriptors2 == NULL) {
+        Print (L"CapsuleApp: failed to allocate memory for descriptors\n");
+        Status = EFI_OUT_OF_RESOURCES;
+        goto ERREXIT;
+      }
+
+      //
+      // Point the first list's last element to point to this second list.
+      //
+      TempBlockPtr->Union.ContinuationPointer   = (UINTN) BlockDescriptors2;
+
+      TempBlockPtr->Length  = 0;
+      TempBlockPtr = BlockDescriptors2;
+      for (Number = 0; Number < Count - 1; Number++) {
+        //
+        // If second-to-last one, then dump rest to this element
+        //
+        if (Number == (Count - 2)) {
+          Size = SizeLeft;
+        } else {
+          //
+          // Divide remaining data in half
+          //
+          if (SizeLeft == 1) {
+            Size = 1;
+          } else {
+            Size = SizeLeft / 2;
+          }
+        }
+
+        TempBlockPtr->Union.DataBlock    = (UINTN)TempDataPtr;
+        TempBlockPtr->Length  = Size;
+        Print (L"CapsuleApp: capsule block/size              0x%X/0x%X\n", (UINTN) TempDataPtr, Size);
+        SizeLeft -= Size;
+        TempDataPtr += Size;
+        TempBlockPtr++;
+        if (SizeLeft == 0) {
+          break;
+        }
+      }
+    }
+
+    BlockDescriptorPre = TempBlockPtr;
+    BlockDescriptors1  = NULL;
+  }
+
+  //
+  // Null-terminate.
+  //
+  if (TempBlockPtr != NULL) {
+    TempBlockPtr->Union.ContinuationPointer    = (UINTN)NULL;
+    TempBlockPtr->Length  = 0;
+    *BlockDescriptors = BlockDescriptorsHeader;
+  }
+
+  return EFI_SUCCESS;
+
+ERREXIT:
+  if (BlockDescriptors1 != NULL) {
+    FreePool(BlockDescriptors1);
+  }
+
+  if (BlockDescriptors2 != NULL) {
+    FreePool(BlockDescriptors2);
+  }
+
+  return Status;
+}
+
+/**
+  Clear the Gather list for a list of capsule images.
+
+  @param[in]  BlockDescriptors The block descriptors for the capsule images
+  @param[in]  CapsuleNum       The count of capsule images
+**/
+VOID
+CleanGatherList(
+  IN EFI_CAPSULE_BLOCK_DESCRIPTOR   *BlockDescriptors,
+  IN UINTN                          CapsuleNum
+  )
+{
+  EFI_CAPSULE_BLOCK_DESCRIPTOR   *TempBlockPtr;
+  EFI_CAPSULE_BLOCK_DESCRIPTOR   *TempBlockPtr1;
+  EFI_CAPSULE_BLOCK_DESCRIPTOR   *TempBlockPtr2;
+  UINTN                          Index;
+
+  if (BlockDescriptors != NULL) {
+    TempBlockPtr1 = BlockDescriptors;
+    while (1){
+      TempBlockPtr = TempBlockPtr1;
+      for (Index = 0; Index < CapsuleNum; Index++) {
+        if (TempBlockPtr[Index].Length == 0) {
+          break;
+        }
+      }
+
+      if (TempBlockPtr[Index].Union.ContinuationPointer == (UINTN)NULL) {
+        break;
+      }
+
+      TempBlockPtr2 = (VOID *) ((UINTN) TempBlockPtr->Union.ContinuationPointer);
+      FreePool(TempBlockPtr1);
+      TempBlockPtr1 = TempBlockPtr2;
+    }
+  }
+}
+
+/**
+  Print APP usage.
+**/
+VOID
+PrintUsage (
+  VOID
+  )
+{
+  Print(L"CapsuleApp:  usage\n");
+  Print(L"  CapsuleApp [-F] <Capsule...> [-NR]\n");
+  Print(L"  CapsuleApp -S\n");
+  Print(L"  CapsuleApp -C\n");
+  Print(L"  CapsuleApp -P\n");
+  Print(L"  CapsuleApp -E\n");
+  Print(L"  CapsuleApp -G <BMP> -O <Capsule>\n");
+  Print(L"  CapsuleApp -N <Capsule> -O <NestedCapsule>\n");
+  Print(L"  CapsuleApp -D|-DS <Capsule>\n");
+  Print(L"Parameter:\n");
+  Print(L"  -F:  Put capsule file to disk.\n");
+  Print(L"       No -F means to put capsule file in memory.\n");
+  Print(L"  -NR: No Reset.\n");
+  Print(L"  -S:  Dump capsule status.\n");
+  Print(L"  -C:  Clear capsule status.\n");
+  Print(L"  -P:  Dump FMP protocol info.\n");
+  Print(L"  -E:  Dump ESRT table info.\n");
+  Print(L"  -G:  Input BMP file name\n");
+  Print(L"  -N:  Append Capsule Header accroding to Windows Firmware Update\n");
+  Print(L"  -O:  Output Capsule file name\n");
+  Print(L"  -D:  Dump Capsule\n");
+  Print(L"  -DS: Dump Capsule with System FMP format\n");
+}
+
+/**
+  Update Capsule image.
+
+  @param[in]  ImageHandle     The image handle.
+  @param[in]  SystemTable     The system table.
+
+  @retval EFI_SUCCESS            Command completed successfully.
+  @retval EFI_INVALID_PARAMETER  Command usage error.
+  @retval EFI_NOT_FOUND          The input file can't be found.
+**/
+EFI_STATUS
+EFIAPI
+UefiMain (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  )
+{
+  EFI_STATUS                    Status;
+  UINTN                         FileSize[MAX_CAPSULE_NUM];
+  VOID                          *CapsuleBuffer[MAX_CAPSULE_NUM];
+  EFI_CAPSULE_BLOCK_DESCRIPTOR  *BlockDescriptors;
+  EFI_CAPSULE_HEADER             *CapsuleHeaderArray[MAX_CAPSULE_NUM + 1];
+  UINT64                         MaxCapsuleSize;
+  EFI_RESET_TYPE                 ResetType;
+  BOOLEAN                        NeedReset;
+  BOOLEAN                        NoReset;
+  BOOLEAN                        NeedCopyOnDisk;
+  CHAR16                         *CapsuleName;
+  UINTN                          CapsuleNum;
+  UINTN                          Index;
+
+  Status = GetArg();
+  if (EFI_ERROR(Status)) {
+    PrintUsage();
+    return Status;
+  }
+  if (Argc < 2) {
+    PrintUsage();
+    CleanArg();
+    return EFI_INVALID_PARAMETER;
+  }
+  if ((StrCmp(Argv[1], L"-D") == 0) ||
+      (StrCmp(Argv[1], L"-DS") == 0)) {
+    Status = DumpCapsule();
+    CleanArg();
+    return Status;
+  }
+  if (StrCmp(Argv[1], L"-G") == 0) {
+    Status = CreateBmpFmp();
+    CleanArg();
+    return Status;
+  }
+  if (StrCmp(Argv[1], L"-N") == 0) {
+    Status = CreateNestedFmp();
+    CleanArg();
+    return Status;
+  }
+  if (StrCmp(Argv[1], L"-S") == 0) {
+    Status = DmpCapsuleStatusVariable();
+    CleanArg();
+    return EFI_SUCCESS;
+  }
+  if (StrCmp(Argv[1], L"-C") == 0) {
+    Status = ClearCapsuleStatusVariable();
+    CleanArg();
+    return Status;
+  }
+  if (StrCmp(Argv[1], L"-P") == 0) {
+    DumpFmpData();
+    CleanArg();
+    return EFI_SUCCESS;
+  }
+  if (StrCmp(Argv[1], L"-E") == 0) {
+    DumpEsrtData();
+    CleanArg();
+    return EFI_SUCCESS;
+  }
+  if (StrCmp(Argv[1], L"-F") == 0) {
+    NeedCopyOnDisk = TRUE;
+    CapsuleFirstIndex = 2;
+  } else {
+    NeedCopyOnDisk = FALSE;
+    CapsuleFirstIndex = 1;
+  }
+  if (StrCmp(Argv[Argc - 1], L"-NR") == 0) {
+    NoReset = TRUE;
+    CapsuleLastIndex = Argc - 2;
+  } else {
+    NoReset = FALSE;
+    CapsuleLastIndex = Argc - 1;
+  }
+  CapsuleNum = CapsuleLastIndex - CapsuleFirstIndex + 1;
+
+  if (CapsuleFirstIndex > CapsuleLastIndex) {
+    Print(L"CapsuleApp: NO capsule image.\n");
+    CleanArg();
+    return EFI_UNSUPPORTED;
+  }
+  if (CapsuleNum > MAX_CAPSULE_NUM) {
+    Print(L"CapsuleApp: Too many capsule images.\n");
+    CleanArg();
+    return EFI_UNSUPPORTED;
+  }
+
+  ZeroMem(&CapsuleBuffer, sizeof(CapsuleBuffer));
+  ZeroMem(&FileSize, sizeof(FileSize));
+  BlockDescriptors = NULL;
+
+  for (Index = 0; Index < CapsuleNum; Index++) {
+    CapsuleName = Argv[CapsuleFirstIndex + Index];
+    Status = ReadFileToBuffer(CapsuleName, &FileSize[Index], &CapsuleBuffer[Index]);
+    if (EFI_ERROR(Status)) {
+      Print(L"CapsuleApp: capsule image (%s) is not found.\n", CapsuleName);
+      goto Done;
+    }
+  }
+
+  if (NeedCopyOnDisk) {
+    Status = CopyCapsuleToActiveEfiPartition(CapsuleBuffer, FileSize, CapsuleNum);
+  } else {
+    //
+    // Every capsule use 2 descriptor 1 for data 1 for end
+    //
+    Status = BuildGatherList(CapsuleBuffer, FileSize, CapsuleNum, &BlockDescriptors);
+  }
+  if (EFI_ERROR(Status)) {
+    goto Done;
+  }
+
+  //
+  // Call the runtime service capsule.
+  //
+  NeedReset = FALSE;
+  for (Index = 0; Index < CapsuleNum; Index++) {
+    CapsuleHeaderArray[Index] = (EFI_CAPSULE_HEADER *) CapsuleBuffer[Index];
+    if ((CapsuleHeaderArray[Index]->Flags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET) != 0) {
+      NeedReset = TRUE;
+    }
+  }
+  CapsuleHeaderArray[CapsuleNum] = NULL;
+  if (NoReset) {
+    NeedReset = FALSE;
+  }
+
+  //
+  // Inquire platform capability of UpdateCapsule.
+  //
+  Status = gRT->QueryCapsuleCapabilities (CapsuleHeaderArray, CapsuleNum, &MaxCapsuleSize, &ResetType);
+  if (EFI_ERROR(Status)) {
+    Print (L"CapsuleApp: failed to query capsule capability - %r\n", Status);
+    goto Done;
+  }
+
+  for (Index = 0; Index < CapsuleNum; Index++) {
+    if (FileSize[Index] > MaxCapsuleSize) {
+      Print (L"CapsuleApp: capsule is too large to update, %ld is allowed\n", MaxCapsuleSize);
+      Status = EFI_UNSUPPORTED;
+      goto Done;
+    }
+  }
+
+  //
+  // Check whether the input capsule image has the flag of persist across system reset.
+  //
+  if (NeedReset) {
+    Status = gRT->UpdateCapsule(CapsuleHeaderArray,CapsuleNum,(UINTN) BlockDescriptors);
+    if (Status != EFI_SUCCESS) {
+      Print (L"CapsuleApp: failed to update capsule - %r\n", Status);
+      goto Done;
+    }
+    //
+    // For capsule who has reset flag, after calling UpdateCapsule service,triger a
+    // system reset to process capsule persist across a system reset.
+    //
+    gRT->ResetSystem (ResetType, EFI_SUCCESS, 0, NULL);
+  } else {
+    //
+    // For capsule who has no reset flag, only call UpdateCapsule Service without a
+    // system reset. The service will process the capsule immediately.
+    //
+    Status = gRT->UpdateCapsule (CapsuleHeaderArray,CapsuleNum,(UINTN) BlockDescriptors);
+    if (Status != EFI_SUCCESS) {
+      Print (L"CapsuleApp: failed to update capsule - %r\n", Status);
+    }
+  }
+
+  Status = EFI_SUCCESS;
+
+Done:
+  for (Index = 0; Index < CapsuleNum; Index++) {
+    if (CapsuleBuffer[Index] != NULL) {
+      FreePool (CapsuleBuffer[Index]);
+    }
+  }
+
+  CleanGatherList(BlockDescriptors, CapsuleNum);
+  CleanArg();
+
+  return Status;
+}
diff --git a/MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf
new file mode 100644
index 0000000..7ee44fc
--- /dev/null
+++ b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf
@@ -0,0 +1,71 @@
+##  @file
+#  A shell application that triggers capsule update process.
+#
+# This application can trigger capsule update process. It can also
+# generate capsule image, or dump capsule variable information.
+#
+#  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010006
+  BASE_NAME                      = CapsuleApp
+  MODULE_UNI_FILE                = CapsuleApp.uni
+  FILE_GUID                      = 4CEF31DA-8682-4274-9CC4-AEE7516A5E7B
+  MODULE_TYPE                    = UEFI_APPLICATION
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = UefiMain
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64
+#
+
+[Sources]
+  CapsuleApp.c
+  CapsuleDump.c
+  AppSupport.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+
+[Guids]
+  gEfiFileInfoGuid
+  gEfiPartTypeSystemPartGuid
+  gEfiGlobalVariableGuid
+  gEfiCapsuleReportGuid
+  gEfiFmpCapsuleGuid
+  gWindowsUxCapsuleGuid
+  gEfiCertTypeRsa2048Sha256Guid
+  gEfiCertPkcs7Guid
+  gEfiSystemResourceTableGuid
+
+[Protocols]
+  gEfiLoadedImageProtocolGuid
+  gEfiSimpleFileSystemProtocolGuid
+  gEfiGraphicsOutputProtocolGuid
+  gEfiFirmwareManagementProtocolGuid
+
+[LibraryClasses]
+  BaseLib
+  UefiApplicationEntryPoint
+  DebugLib
+  MemoryAllocationLib
+  UefiBootServicesTableLib
+  UefiRuntimeServicesTableLib
+  UefiLib
+  PrintLib
+  EdkiiSystemCapsuleLib
+
+[UserExtensions.TianoCore."ExtraFiles"]
+  CapsuleAppExtra.uni
diff --git a/MdeModulePkg/Application/CapsuleApp/CapsuleApp.uni b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.uni
new file mode 100644
index 0000000..54d6e12
--- /dev/null
+++ b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.uni
@@ -0,0 +1,22 @@
+// /** @file
+// A shell application that triggers capsule update process.
+//
+// This application can trigger capsule update process. It can also
+// generate capsule image, or dump capsule variable information.
+//
+// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+//
+// This program and the accompanying materials
+// are licensed and made available under the terms and conditions of the BSD License
+// which accompanies this distribution. The full text of the license may be found at
+// http://opensource.org/licenses/bsd-license.php
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT             #language en-US "A shell application that triggers capsule update process."
+
+#string STR_MODULE_DESCRIPTION          #language en-US "This application can trigger capsule update process. It can also generate capsule image, or dump capsule variable information."
+
diff --git a/MdeModulePkg/Application/CapsuleApp/CapsuleAppExtra.uni b/MdeModulePkg/Application/CapsuleApp/CapsuleAppExtra.uni
new file mode 100644
index 0000000..b5a8840
--- /dev/null
+++ b/MdeModulePkg/Application/CapsuleApp/CapsuleAppExtra.uni
@@ -0,0 +1,19 @@
+// /** @file
+// CapsuleApp Localized Strings and Content
+//
+// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+//
+// This program and the accompanying materials
+// are licensed and made available under the terms and conditions of the BSD License
+// which accompanies this distribution. The full text of the license may be found at
+// http://opensource.org/licenses/bsd-license.php
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+// **/
+
+#string STR_PROPERTIES_MODULE_NAME
+#language en-US
+"Capsule Application"
+
+
diff --git a/MdeModulePkg/Application/CapsuleApp/CapsuleDump.c b/MdeModulePkg/Application/CapsuleApp/CapsuleDump.c
new file mode 100644
index 0000000..c56f41f
--- /dev/null
+++ b/MdeModulePkg/Application/CapsuleApp/CapsuleDump.c
@@ -0,0 +1,840 @@
+/** @file
+  Dump Capsule image information.
+
+  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <PiDxe.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/UefiLib.h>
+#include <Library/PrintLib.h>
+#include <Library/EdkiiSystemCapsuleLib.h>
+#include <Protocol/FirmwareManagement.h>
+#include <Guid/ImageAuthentication.h>
+#include <Guid/EdkiiSystemFmpCapsule.h>
+#include <Guid/CapsuleReport.h>
+#include <Guid/SystemResourceTable.h>
+#include <Guid/FmpCapsule.h>
+#include <IndustryStandard/WindowsUxCapsule.h>
+
+/**
+  Read a file.
+
+  @param FileName        The file to be read.
+  @param BufferSize      The file buffer size
+  @param Buffer          The file buffer
+
+  @retval EFI_SUCCESS    Read file successfully
+  @retval EFI_NOT_FOUND  File not found
+**/
+EFI_STATUS
+ReadFileToBuffer(
+  IN  CHAR16                               *FileName,
+  OUT UINTN                                *BufferSize,
+  OUT VOID                                 **Buffer
+  );
+
+extern UINTN  Argc;
+extern CHAR16 *Argv[];
+
+/**
+  Dump UX capsule information.
+
+  @param CapsuleHeader      The UX capsule header
+**/
+VOID
+DumpUxCapsule(
+  IN EFI_CAPSULE_HEADER  *CapsuleHeader
+  )
+{
+  EFI_DISPLAY_CAPSULE                           *DisplayCapsule;
+  DisplayCapsule = (EFI_DISPLAY_CAPSULE *)CapsuleHeader;
+  Print(L"[UxCapusule]\n");
+  Print(L"CapsuleHeader:\n");
+  Print(L"  CapsuleGuid      - %g\n", &DisplayCapsule->CapsuleHeader.CapsuleGuid);
+  Print(L"  HeaderSize       - 0x%x\n", DisplayCapsule->CapsuleHeader.HeaderSize);
+  Print(L"  Flags            - 0x%x\n", DisplayCapsule->CapsuleHeader.Flags);
+  Print(L"  CapsuleImageSize - 0x%x\n", DisplayCapsule->CapsuleHeader.CapsuleImageSize);
+  Print(L"ImagePayload:\n");
+  Print(L"  Version          - 0x%x\n", DisplayCapsule->ImagePayload.Version);
+  Print(L"  Checksum         - 0x%x\n", DisplayCapsule->ImagePayload.Checksum);
+  Print(L"  ImageType        - 0x%x\n", DisplayCapsule->ImagePayload.ImageType);
+  Print(L"  Mode             - 0x%x\n", DisplayCapsule->ImagePayload.Mode);
+  Print(L"  OffsetX          - 0x%x\n", DisplayCapsule->ImagePayload.OffsetX);
+  Print(L"  OffsetY          - 0x%x\n", DisplayCapsule->ImagePayload.OffsetY);
+}
+
+/**
+  Dump FMP image authentication information.
+
+  @param Image      The FMP capsule image
+  @param ImageSize  The size of the FMP capsule image in bytes.
+
+  @return the size of FMP authentication.
+**/
+UINTN
+DumpImageAuthentication(
+  IN VOID   *Image,
+  IN UINTN  ImageSize
+  )
+{
+  EFI_FIRMWARE_IMAGE_AUTHENTICATION             *ImageAuthentication;
+
+  ImageAuthentication = Image;
+  if (CompareGuid(&ImageAuthentication->AuthInfo.CertType, &gEfiCertPkcs7Guid) ||
+      CompareGuid(&ImageAuthentication->AuthInfo.CertType, &gEfiCertTypeRsa2048Sha256Guid)) {
+    Print(L"[ImageAuthentication]\n");
+    Print(L"  MonotonicCount   - 0x%lx\n", ImageAuthentication->MonotonicCount);
+    Print(L"WIN_CERTIFICATE:\n");
+    Print(L"  dwLength         - 0x%x\n", ImageAuthentication->AuthInfo.Hdr.dwLength);
+    Print(L"  wRevision        - 0x%x\n", ImageAuthentication->AuthInfo.Hdr.wRevision);
+    Print(L"  wCertificateType - 0x%x\n", ImageAuthentication->AuthInfo.Hdr.wCertificateType);
+    Print(L"  CertType         - %g\n", &ImageAuthentication->AuthInfo.CertType);
+    return sizeof(ImageAuthentication->MonotonicCount) + ImageAuthentication->AuthInfo.Hdr.dwLength;
+  } else {
+    return 0;
+  }
+}
+
+/**
+  Dump EDKII system FMP capsule.
+
+  @param Image      The EDKII system FMP capsule.
+  @param ImageSize  The size of the EDKII system FMP capsule in bytes.
+**/
+VOID
+DumpEdkiiSystemFmpCapsule(
+  IN VOID   *Image,
+  IN UINTN  ImageSize
+  )
+{
+  UINTN                                         ImageOffset;
+  VOID                                          *BiosImage;
+  UINTN                                         BiosImageSize;
+  BOOLEAN                                       Result;
+  EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR        *TempImageFmpInfo;
+  EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR        *ImageFmpInfo;
+  UINTN                                         ImageFmpInfoSize;
+
+  //
+  // We do not know if there is EFI_FIRMWARE_IMAGE_AUTHENTICATION.
+  // so just *try* to parse it
+  //
+  ImageOffset = DumpImageAuthentication(Image, ImageSize);
+  Image = (UINT8 *)Image + ImageOffset;
+  ImageSize -= ImageOffset;
+  Print(L"[Image]\n");
+  Print(L"  ImageSize   - 0x%x\n", ImageSize);
+
+  Result = ExtractConfigImage(Image, ImageSize, &BiosImage, &BiosImageSize);
+  if (Result) {
+    Print(L"  ConfigFileSize  - 0x%x\n", BiosImageSize);
+  }
+  Result = ExtractDriverFvImage(Image, ImageSize, &BiosImage, &BiosImageSize);
+  if (Result) {
+    Print(L"  DriverFvSize    - 0x%x\n", BiosImageSize);
+  }
+  Result = ExtractSystemFirmwareImage(Image, ImageSize, &BiosImage, &BiosImageSize);
+  if (Result) {
+    Print(L"  BiosImageSize   - 0x%x\n", BiosImageSize);
+  }
+  Result = ExtractSystemFirmwareImageFmpInfo(BiosImage, BiosImageSize, &TempImageFmpInfo, &ImageFmpInfoSize);
+  if (Result) {
+    ImageFmpInfo = AllocateCopyPool(ImageFmpInfoSize, TempImageFmpInfo);
+    if (ImageFmpInfo != NULL) {
+      Print(L"[ImageFmpInfo]\n");
+      Print(L"  Signature                      - 0x%x\n", ImageFmpInfo->Signature);
+      Print(L"  HeaderLength                   - 0x%x\n", ImageFmpInfo->HeaderLength);
+      Print(L"  Length                         - 0x%x\n", ImageFmpInfo->Length);
+      Print(L"  PackageVersion                 - 0x%x\n", ImageFmpInfo->PackageVersion);
+      Print(L"  PackageVersionNameStringOffset - 0x%x\n", ImageFmpInfo->PackageVersionNameStringOffset);
+      if (ImageFmpInfo->PackageVersionNameStringOffset != 0) {
+        Print(L"                                 - %s\n", (UINT8 *)ImageFmpInfo + ImageFmpInfo->PackageVersionNameStringOffset);
+      }
+      Print(L"  ImageIndex                     - 0x%x\n", ImageFmpInfo->ImageIndex);
+      Print(L"  ImageTypeId                    - %g\n", &ImageFmpInfo->ImageTypeId);
+      Print(L"  ImageId                        - 0x%lx\n", ImageFmpInfo->ImageId);
+      Print(L"  ImageIdNameStringOffset        - 0x%x\n", ImageFmpInfo->ImageIdNameStringOffset);
+      if (ImageFmpInfo->ImageIdNameStringOffset != 0) {
+        Print(L"                                 - %s\n", (UINT8 *)ImageFmpInfo + ImageFmpInfo->ImageIdNameStringOffset);
+      }
+      Print(L"  Version                        - 0x%x\n", ImageFmpInfo->Version);
+      Print(L"  VersionNameStringOffset        - 0x%x\n", ImageFmpInfo->VersionNameStringOffset);
+      if (ImageFmpInfo->VersionNameStringOffset != 0) {
+        Print(L"                                 - %s\n", (UINT8 *)ImageFmpInfo + ImageFmpInfo->VersionNameStringOffset);
+      }
+      Print(L"  Size                           - 0x%lx\n", ImageFmpInfo->Size);
+      Print(L"  AttributesSupported            - 0x%lx\n", ImageFmpInfo->AttributesSupported);
+      Print(L"  AttributesSetting              - 0x%lx\n", ImageFmpInfo->AttributesSetting);
+      Print(L"  Compatibilities                - 0x%lx\n", ImageFmpInfo->Compatibilities);
+      Print(L"  LowestSupportedImageVersion    - 0x%x\n", ImageFmpInfo->LowestSupportedImageVersion);
+      Print(L"  LastAttemptVersion             - 0x%x\n", ImageFmpInfo->LastAttemptVersion);
+      Print(L"  LastAttemptStatus              - 0x%x\n", ImageFmpInfo->LastAttemptStatus);
+      Print(L"  HardwareInstance               - 0x%lx\n", ImageFmpInfo->HardwareInstance);
+      Print(L"  Version                        - 0x%x\n", ImageFmpInfo->Version);
+      FreePool(ImageFmpInfo);
+    }
+  }
+}
+
+/**
+  Dump a non-nested FMP capsule.
+
+  @param  CapsuleHeader  A pointer to CapsuleHeader
+  @param  IsSystemFmp    If it is a system FMP
+**/
+VOID
+DumpFmpCapsule(
+  IN EFI_CAPSULE_HEADER  *CapsuleHeader,
+  IN BOOLEAN             IsSystemFmp
+  )
+{
+  EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER        *FmpCapsuleHeader;
+  UINT64                                        *ItemOffsetList;
+  UINTN                                         Index;
+  UINTN                                         Count;
+  EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER  *FmpImageHeader;
+  VOID                                          *Image;
+
+  Print(L"[FmpCapusule]\n");
+  Print(L"CapsuleHeader:\n");
+  Print(L"  CapsuleGuid      - %g\n", &CapsuleHeader->CapsuleGuid);
+  Print(L"  HeaderSize       - 0x%x\n", CapsuleHeader->HeaderSize);
+  Print(L"  Flags            - 0x%x\n", CapsuleHeader->Flags);
+  Print(L"  CapsuleImageSize - 0x%x\n", CapsuleHeader->CapsuleImageSize);
+
+  FmpCapsuleHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *)((UINT8 *)CapsuleHeader + CapsuleHeader->HeaderSize);
+  ItemOffsetList = (UINT64 *)(FmpCapsuleHeader + 1);
+  Print(L"FmpHeader:\n");
+  Print(L"  Version             - 0x%x\n", FmpCapsuleHeader->Version);
+  Print(L"  EmbeddedDriverCount - 0x%x\n", FmpCapsuleHeader->EmbeddedDriverCount);
+  Print(L"  PayloadItemCount    - 0x%x\n", FmpCapsuleHeader->PayloadItemCount);
+  Count = FmpCapsuleHeader->EmbeddedDriverCount + FmpCapsuleHeader->PayloadItemCount;
+  for (Index = 0; Index < Count; Index++) {
+    Print(L"  Offset[%d]           - 0x%x\n", Index, ItemOffsetList[Index]);
+  }
+
+  for (Index = FmpCapsuleHeader->EmbeddedDriverCount; Index < Count; Index++) {
+    Print(L"FmpPayload[%d] ImageHeader:\n", Index);
+    FmpImageHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *)((UINT8 *)FmpCapsuleHeader + ItemOffsetList[Index]);
+    Print(L"  Version                - 0x%x\n", FmpImageHeader->Version);
+    Print(L"  UpdateImageTypeId      - %g\n", &FmpImageHeader->UpdateImageTypeId);
+    Print(L"  UpdateImageIndex       - 0x%x\n", FmpImageHeader->UpdateImageIndex);
+    Print(L"  UpdateImageSize        - 0x%x\n", FmpImageHeader->UpdateImageSize);
+    Print(L"  UpdateVendorCodeSize   - 0x%x\n", FmpImageHeader->UpdateVendorCodeSize);
+    if (FmpImageHeader->Version >= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {
+      Print(L"  UpdateHardwareInstance - 0x%lx\n", FmpImageHeader->UpdateHardwareInstance);
+    }
+    if (FmpImageHeader->Version >= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {
+      Image = (UINT8 *)(FmpImageHeader + 1);
+    }  else {
+      Image = (UINT8 *)FmpImageHeader + OFFSET_OF(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER, UpdateHardwareInstance);
+    }
+    if (IsSystemFmp) {
+      DumpEdkiiSystemFmpCapsule(Image, FmpImageHeader->UpdateImageSize);
+    }
+  }
+}
+
+/**
+  Return if there is a FMP header below capsule header.
+
+  @param[in] CapsuleHeader A pointer to EFI_CAPSULE_HEADER
+
+  @retval TRUE  There is a FMP header below capsule header.
+  @retval FALSE There is not a FMP header below capsule header
+**/
+BOOLEAN
+IsNestedFmpCapsule(
+  IN EFI_CAPSULE_HEADER         *CapsuleHeader
+  )
+{
+  EFI_STATUS                 Status;
+  EFI_SYSTEM_RESOURCE_TABLE  *Esrt;
+  EFI_SYSTEM_RESOURCE_ENTRY  *EsrtEntry;
+  UINTN                      Index;
+  BOOLEAN                    EsrtGuidFound;
+  EFI_CAPSULE_HEADER         *NestedCapsuleHeader;
+  UINTN                      NestedCapsuleSize;
+
+  //
+  // Check ESRT
+  //
+  EsrtGuidFound = FALSE;
+  Status = EfiGetSystemConfigurationTable(&gEfiSystemResourceTableGuid, (VOID **)&Esrt);
+  if (!EFI_ERROR(Status)) {
+    EsrtEntry = (VOID *)(Esrt + 1);
+    for (Index = 0; Index < Esrt->FwResourceCount; Index++, EsrtEntry++) {
+      if (CompareGuid(&EsrtEntry->FwClass, &CapsuleHeader->CapsuleGuid)) {
+        EsrtGuidFound = TRUE;
+        break;
+      }
+    }
+  }
+
+  if (!EsrtGuidFound) {
+    return FALSE;
+  }
+
+  //
+  // Check nested capsule header
+  // FMP GUID after ESRT one
+  //
+  NestedCapsuleHeader = (EFI_CAPSULE_HEADER *)((UINT8 *)CapsuleHeader + CapsuleHeader->HeaderSize);
+  NestedCapsuleSize = (UINTN)CapsuleHeader + CapsuleHeader->HeaderSize - (UINTN)NestedCapsuleHeader;
+  if (NestedCapsuleSize < sizeof(EFI_CAPSULE_HEADER)) {
+    return FALSE;
+  }
+  if (!CompareGuid(&NestedCapsuleHeader->CapsuleGuid, &gEfiFmpCapsuleGuid)) {
+    return FALSE;
+  }
+  return TRUE;
+}
+
+/**
+  Dump capsule information
+
+  @retval EFI_SUCCESS            The capsule information is dumped.
+  @retval EFI_UNSUPPORTED        Input parameter is not valid.
+**/
+EFI_STATUS
+DumpCapsule(
+  VOID
+  )
+{
+  CHAR16                                        *CapsuleName;
+  VOID                                          *Buffer;
+  UINTN                                         FileSize;
+  BOOLEAN                                       IsSystemFmp;
+  EFI_CAPSULE_HEADER                            *CapsuleHeader;
+  EFI_STATUS                                    Status;
+
+  if (Argc != 3) {
+    Print(L"CapsuleApp: Invalid Parameter.\n");
+    return EFI_UNSUPPORTED;
+  }
+
+  IsSystemFmp = FALSE;
+  if (StrCmp(Argv[1], L"-DS") == 0) {
+    IsSystemFmp = TRUE;
+  }
+
+  CapsuleName = Argv[2];
+  Status = ReadFileToBuffer(CapsuleName, &FileSize, &Buffer);
+  if (EFI_ERROR(Status)) {
+    Print(L"CapsuleApp: Capsule (%s) is not found.\n", CapsuleName);
+    goto Done;
+  }
+
+  CapsuleHeader = Buffer;
+  if (CompareGuid(&CapsuleHeader->CapsuleGuid, &gWindowsUxCapsuleGuid)) {
+    DumpUxCapsule(CapsuleHeader);
+    Status = EFI_SUCCESS;
+    goto Done;
+  }
+
+  if (CompareGuid(&CapsuleHeader->CapsuleGuid, &gEfiFmpCapsuleGuid)) {
+    DumpFmpCapsule(CapsuleHeader, IsSystemFmp);
+  }
+  if (IsNestedFmpCapsule(CapsuleHeader)) {
+    Print(L"[NestedCapusule]\n");
+    Print(L"CapsuleHeader:\n");
+    Print(L"  CapsuleGuid      - %g\n", &CapsuleHeader->CapsuleGuid);
+    Print(L"  HeaderSize       - 0x%x\n", CapsuleHeader->HeaderSize);
+    Print(L"  Flags            - 0x%x\n", CapsuleHeader->Flags);
+    Print(L"  CapsuleImageSize - 0x%x\n", CapsuleHeader->CapsuleImageSize);
+    DumpFmpCapsule((EFI_CAPSULE_HEADER *)((UINTN)CapsuleHeader + CapsuleHeader->HeaderSize), IsSystemFmp);
+  }
+
+Done:
+  FreePool(Buffer);
+  return Status;
+}
+
+/**
+  Dump capsule status variable.
+
+  @retval EFI_SUCCESS            The capsule status variable is dumped.
+  @retval EFI_UNSUPPORTED        Input parameter is not valid.
+**/
+EFI_STATUS
+DmpCapsuleStatusVariable(
+  VOID
+  )
+{
+  EFI_STATUS                          Status;
+  UINT32                              Index;
+  CHAR16                              CapsuleVarName[20];
+  CHAR16                              *TempVarName;
+  EFI_CAPSULE_RESULT_VARIABLE_HEADER  *CapsuleResult;
+  EFI_CAPSULE_RESULT_VARIABLE_FMP     *CapsuleResultFmp;
+  UINTN                               CapsuleFileNameSize;
+  CHAR16                              CapsuleIndexData[12];
+  CHAR16                              *CapsuleIndex;
+
+  Status = GetVariable2(
+             L"CapsuleMax",
+             &gEfiCapsuleReportGuid,
+             (VOID **)&CapsuleIndex,
+             NULL
+             );
+  if (!EFI_ERROR(Status)) {
+    CopyMem(CapsuleIndexData, CapsuleIndex, 11 * sizeof(CHAR16));
+    CapsuleIndexData[11] = 0;
+    Print(L"CapsuleMax - %s\n", CapsuleIndexData);
+    FreePool(CapsuleIndex);
+  }
+  Status = GetVariable2(
+             L"CapsuleLast",
+             &gEfiCapsuleReportGuid,
+             (VOID **)&CapsuleIndex,
+             NULL
+             );
+  if (!EFI_ERROR(Status)) {
+    CopyMem(CapsuleIndexData, CapsuleIndex, 11 * sizeof(CHAR16));
+    CapsuleIndexData[11] = 0;
+    Print(L"CapsuleLast - %s\n", CapsuleIndexData);
+    FreePool(CapsuleIndex);
+  }
+
+
+  StrCpyS (CapsuleVarName, sizeof(CapsuleVarName)/sizeof(CapsuleVarName[0]), L"Capsule");
+  TempVarName = CapsuleVarName + StrLen (CapsuleVarName);
+  Index = 0;
+
+  while (TRUE) {
+    UnicodeSPrint (TempVarName, 5 * sizeof(CHAR16), L"%04x", Index);
+
+    Status = GetVariable2 (
+               CapsuleVarName,
+               &gEfiCapsuleReportGuid,
+               (VOID **) &CapsuleResult,
+               NULL
+               );
+    if (Status == EFI_NOT_FOUND) {
+      break;
+    } else if (EFI_ERROR(Status)) {
+      continue;
+    }
+
+    //
+    // display capsule process status
+    //
+    if (CapsuleResult->VariableTotalSize >= sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER)) {
+      Print (L"CapsuleName: %s\n", CapsuleVarName);
+      Print (L"  Capsule Guid: %g\n", &CapsuleResult->CapsuleGuid);
+      Print (L"  Capsule ProcessedTime: %t\n", &CapsuleResult->CapsuleProcessed);
+      Print (L"  Capsule Status: %r\n", CapsuleResult->CapsuleStatus);
+    }
+
+    if (CompareGuid(&CapsuleResult->CapsuleGuid, &gEfiFmpCapsuleGuid)) {
+      if (CapsuleResult->VariableTotalSize >= sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER) + sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP)) {
+        CapsuleResultFmp = (EFI_CAPSULE_RESULT_VARIABLE_FMP *)(CapsuleResult + 1);
+        Print(L"  Capsule FMP Version: 0x%x\n", CapsuleResultFmp->Version);
+        Print(L"  Capsule FMP PayloadIndex: 0x%x\n", CapsuleResultFmp->PayloadIndex);
+        Print(L"  Capsule FMP UpdateImageIndex: 0x%x\n", CapsuleResultFmp->UpdateImageIndex);
+        Print(L"  Capsule FMP UpdateImageTypeId: %g\n", &CapsuleResultFmp->UpdateImageTypeId);
+        if (CapsuleResult->VariableTotalSize > sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER) + sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP)) {
+          Print(L"  Capsule FMP CapsuleFileName: %s\n", (CapsuleResultFmp + 1));
+          CapsuleFileNameSize = StrSize((CHAR16 *)(CapsuleResultFmp + 1));
+          if (CapsuleResult->VariableTotalSize > sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER) + sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP) + CapsuleFileNameSize) {
+            Print(L"  Capsule FMP CapsuleTarget: %s\n", (UINT8 *)(CapsuleResultFmp + 1) + CapsuleFileNameSize);
+          }
+        }
+      }
+    }
+
+    FreePool(CapsuleResult);
+
+    Index++;
+    if (Index > 0xFFFF) {
+      break;
+    }
+  }
+
+  return EFI_SUCCESS;
+}
+
+CHAR8 *mFwTypeString[] = {
+  "Unknown",
+  "SystemFirmware",
+  "DeviceFirmware",
+  "UefiDriver",
+};
+
+CHAR8 *mLastAttemptStatusString[] = {
+  "Success",
+  "Error: Unsuccessful",
+  "Error: Insufficient Resources",
+  "Error: Incorrect Version",
+  "Error: Invalid Format",
+  "Error: Auth Error",
+  "Error: Power Event AC",
+  "Error: Power Event Battery",
+};
+
+/**
+  Convert FwType to a string.
+
+  @param FwType  FwType in ESRT
+
+  @return a string for FwType.
+**/
+CHAR8 *
+FwTypeToString(
+  IN UINT32 FwType
+  )
+{
+  if (FwType < sizeof(mFwTypeString) / sizeof(mFwTypeString[0])) {
+    return mFwTypeString[FwType];
+  } else {
+    return "Invalid";
+  }
+}
+
+/**
+  Convert LastAttemptStatus to a string.
+
+  @param LastAttemptStatus  LastAttemptStatus in FMP or ESRT
+
+  @return a string for LastAttemptStatus.
+**/
+CHAR8 *
+LastAttemptStatusToString(
+  IN UINT32 LastAttemptStatus
+  )
+{
+  if (LastAttemptStatus < sizeof(mLastAttemptStatusString) / sizeof(mLastAttemptStatusString[0])) {
+    return mLastAttemptStatusString[LastAttemptStatus];
+  } else {
+    return "Error: Unknown";
+  }
+}
+
+/**
+  Dump ESRT entry.
+
+  @param EsrtEntry  ESRT entry
+**/
+VOID
+DumpEsrtEntry(
+  IN EFI_SYSTEM_RESOURCE_ENTRY  *EsrtEntry
+  )
+{
+  Print(L"  FwClass                  - %g\n", &EsrtEntry->FwClass);
+  Print(L"  FwType                   - 0x%x (%a)\n", EsrtEntry->FwType, FwTypeToString(EsrtEntry->FwType));
+  Print(L"  FwVersion                - 0x%x\n", EsrtEntry->FwVersion);
+  Print(L"  LowestSupportedFwVersion - 0x%x\n", EsrtEntry->LowestSupportedFwVersion);
+  Print(L"  CapsuleFlags             - 0x%x\n", EsrtEntry->CapsuleFlags);
+  Print(L"    PERSIST_ACROSS_RESET   - 0x%x\n", EsrtEntry->CapsuleFlags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET);
+  Print(L"    POPULATE_SYSTEM_TABLE  - 0x%x\n", EsrtEntry->CapsuleFlags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE);
+  Print(L"    INITIATE_RESET         - 0x%x\n", EsrtEntry->CapsuleFlags & CAPSULE_FLAGS_INITIATE_RESET);
+  Print(L"  LastAttemptVersion       - 0x%x\n", EsrtEntry->LastAttemptVersion);
+  Print(L"  LastAttemptStatus        - 0x%x (%a)\n", EsrtEntry->LastAttemptStatus, LastAttemptStatusToString(EsrtEntry->LastAttemptStatus));
+}
+
+/**
+  Dump ESRT table.
+
+  @param Esrt  ESRT table
+**/
+VOID
+DumpEsrt(
+  IN EFI_SYSTEM_RESOURCE_TABLE  *Esrt
+  )
+{
+  UINTN                      Index;
+  EFI_SYSTEM_RESOURCE_ENTRY  *EsrtEntry;
+
+  Print(L"EFI_SYSTEM_RESOURCE_TABLE:\n");
+  Print(L"FwResourceCount    - 0x%x\n", Esrt->FwResourceCount);
+  Print(L"FwResourceCountMax - 0x%x\n", Esrt->FwResourceCountMax);
+  Print(L"FwResourceVersion  - 0x%lx\n", Esrt->FwResourceVersion);
+
+  EsrtEntry = (VOID *)(Esrt + 1);
+  for (Index = 0; Index < Esrt->FwResourceCount; Index++) {
+    Print(L"EFI_SYSTEM_RESOURCE_ENTRY (%d):\n", Index);
+    DumpEsrtEntry(EsrtEntry);
+    EsrtEntry++;
+  }
+}
+
+/**
+  Dump ESRT info.
+**/
+VOID
+DumpEsrtData (
+  VOID
+  )
+{
+  EFI_STATUS                 Status;
+  EFI_SYSTEM_RESOURCE_TABLE  *Esrt;
+
+  Print(L"##############\n");
+  Print(L"# ESRT TABLE #\n");
+  Print(L"##############\n");
+
+  Status = EfiGetSystemConfigurationTable (&gEfiSystemResourceTableGuid, (VOID **)&Esrt);
+  if (EFI_ERROR(Status)) {
+    Print(L"ESRT - %r\n", Status);
+    return;
+  }
+  DumpEsrt(Esrt);
+  Print(L"\n");
+}
+
+/**
+  Dump FMP information.
+
+  @param ImageInfoSize       The size of ImageInfo, in bytes.
+  @param ImageInfo           A pointer to EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+  @param DescriptorVersion   The version of EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+  @param DescriptorCount     The count of EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+  @param DescriptorSize      The size of an individual EFI_FIRMWARE_IMAGE_DESCRIPTOR, in bytes.
+  @param PackageVersion      The version of package.
+  @param PackageVersionName  The version name of package.
+**/
+VOID
+DumpFmpImageInfo(
+  IN UINTN                           ImageInfoSize,
+  IN EFI_FIRMWARE_IMAGE_DESCRIPTOR   *ImageInfo,
+  IN UINT32                          DescriptorVersion,
+  IN UINT8                           DescriptorCount,
+  IN UINTN                           DescriptorSize,
+  IN UINT32                          PackageVersion,
+  IN CHAR16                          *PackageVersionName
+  )
+{
+  EFI_FIRMWARE_IMAGE_DESCRIPTOR                 *CurrentImageInfo;
+  UINTN                                         Index;
+
+  Print(L"  DescriptorVersion  - 0x%x\n", DescriptorVersion);
+  Print(L"  DescriptorCount    - 0x%x\n", DescriptorCount);
+  Print(L"  DescriptorSize     - 0x%x\n", DescriptorSize);
+  Print(L"  PackageVersion     - 0x%x\n", PackageVersion);
+  Print(L"  PackageVersionName - \"%s\"\n", PackageVersionName);
+  CurrentImageInfo = ImageInfo;
+  for (Index = 0; Index < DescriptorCount; Index++) {
+    Print(L"  ImageDescriptor (%d)\n", Index);
+    Print(L"    ImageIndex                  - 0x%x\n", CurrentImageInfo->ImageIndex);
+    Print(L"    ImageTypeId                 - %g\n", &CurrentImageInfo->ImageTypeId);
+    Print(L"    ImageId                     - 0x%lx\n", CurrentImageInfo->ImageId);
+    Print(L"    ImageIdName                 - \"%s\"\n", CurrentImageInfo->ImageIdName);
+    Print(L"    Version                     - 0x%x\n", CurrentImageInfo->Version);
+    Print(L"    VersionName                 - \"%s\"\n", CurrentImageInfo->VersionName);
+    Print(L"    Size                        - 0x%x\n", CurrentImageInfo->Size);
+    Print(L"    AttributesSupported         - 0x%lx\n", CurrentImageInfo->AttributesSupported);
+    Print(L"      IMAGE_UPDATABLE           - 0x%lx\n", CurrentImageInfo->AttributesSupported & IMAGE_ATTRIBUTE_IMAGE_UPDATABLE);
+    Print(L"      RESET_REQUIRED            - 0x%lx\n", CurrentImageInfo->AttributesSupported & IMAGE_ATTRIBUTE_RESET_REQUIRED);
+    Print(L"      AUTHENTICATION_REQUIRED   - 0x%lx\n", CurrentImageInfo->AttributesSupported & IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);
+    Print(L"      IN_USE                    - 0x%lx\n", CurrentImageInfo->AttributesSupported & IMAGE_ATTRIBUTE_IN_USE);
+    Print(L"      UEFI_IMAGE                - 0x%lx\n", CurrentImageInfo->AttributesSupported & IMAGE_ATTRIBUTE_UEFI_IMAGE);
+    Print(L"    AttributesSetting           - 0x%lx\n", CurrentImageInfo->AttributesSetting);
+    Print(L"      IMAGE_UPDATABLE           - 0x%lx\n", CurrentImageInfo->AttributesSetting & IMAGE_ATTRIBUTE_IMAGE_UPDATABLE);
+    Print(L"      RESET_REQUIRED            - 0x%lx\n", CurrentImageInfo->AttributesSetting & IMAGE_ATTRIBUTE_RESET_REQUIRED);
+    Print(L"      AUTHENTICATION_REQUIRED   - 0x%lx\n", CurrentImageInfo->AttributesSetting & IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);
+    Print(L"      IN_USE                    - 0x%lx\n", CurrentImageInfo->AttributesSetting & IMAGE_ATTRIBUTE_IN_USE);
+    Print(L"      UEFI_IMAGE                - 0x%lx\n", CurrentImageInfo->AttributesSetting & IMAGE_ATTRIBUTE_UEFI_IMAGE);
+    Print(L"    Compatibilities             - 0x%lx\n", CurrentImageInfo->Compatibilities);
+    Print(L"      COMPATIB_CHECK_SUPPORTED  - 0x%lx\n", CurrentImageInfo->Compatibilities & IMAGE_COMPATIBILITY_CHECK_SUPPORTED);
+    if (DescriptorVersion > 1) {
+      Print(L"    LowestSupportedImageVersion - 0x%x\n", CurrentImageInfo->LowestSupportedImageVersion);
+      if (DescriptorVersion > 2) {
+        Print(L"    LastAttemptVersion          - 0x%x\n", CurrentImageInfo->LastAttemptVersion);
+        Print(L"    LastAttemptStatus           - 0x%x (%a)\n", CurrentImageInfo->LastAttemptStatus, LastAttemptStatusToString(CurrentImageInfo->LastAttemptStatus));
+        Print(L"    HardwareInstance            - 0x%lx\n", CurrentImageInfo->HardwareInstance);
+      }
+    }
+    //
+    // Use DescriptorSize to move ImageInfo Pointer to stay compatible with different ImageInfo version
+    //
+    CurrentImageInfo = (EFI_FIRMWARE_IMAGE_DESCRIPTOR *)((UINT8 *)CurrentImageInfo + DescriptorSize);
+  }
+}
+
+/**
+  Dump FMP package information.
+
+  @param PackageVersion             The version of package.
+  @param PackageVersionName         The version name of package.
+  @param PackageVersionNameMaxLen   The maximum length of PackageVersionName.
+  @param AttributesSupported        Package attributes that are supported by this device.
+  @param AttributesSetting          Package attributes.
+**/
+VOID
+DumpFmpPackageInfo(
+  IN UINT32                           PackageVersion,
+  IN CHAR16                           *PackageVersionName,
+  IN UINT32                           PackageVersionNameMaxLen,
+  IN UINT64                           AttributesSupported,
+  IN UINT64                           AttributesSetting
+  )
+{
+  Print(L"  PackageVersion              - 0x%x\n", PackageVersion);
+  Print(L"  PackageVersionName          - \"%s\"\n", PackageVersionName);
+  Print(L"  PackageVersionNameMaxLen    - 0x%x\n", PackageVersionNameMaxLen);
+  Print(L"  AttributesSupported         - 0x%lx\n", AttributesSupported);
+  Print(L"    IMAGE_UPDATABLE           - 0x%lx\n", AttributesSupported & IMAGE_ATTRIBUTE_IMAGE_UPDATABLE);
+  Print(L"    RESET_REQUIRED            - 0x%lx\n", AttributesSupported & IMAGE_ATTRIBUTE_RESET_REQUIRED);
+  Print(L"    AUTHENTICATION_REQUIRED   - 0x%lx\n", AttributesSupported & IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);
+  Print(L"  AttributesSetting           - 0x%lx\n", AttributesSetting);
+  Print(L"    IMAGE_UPDATABLE           - 0x%lx\n", AttributesSetting & IMAGE_ATTRIBUTE_IMAGE_UPDATABLE);
+  Print(L"    RESET_REQUIRED            - 0x%lx\n", AttributesSetting & IMAGE_ATTRIBUTE_RESET_REQUIRED);
+  Print(L"    AUTHENTICATION_REQUIRED   - 0x%lx\n", AttributesSetting & IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);
+}
+
+/**
+  Dump FMP protocol info.
+**/
+VOID
+DumpFmpData (
+  VOID
+  )
+{
+  EFI_STATUS                                    Status;
+  EFI_FIRMWARE_MANAGEMENT_PROTOCOL              *Fmp;
+  EFI_HANDLE                                    *HandleBuffer;
+  UINTN                                         NumberOfHandles;
+  UINTN                                         Index;
+  EFI_FIRMWARE_IMAGE_DESCRIPTOR                 *FmpImageInfoBuf;
+  UINTN                                         ImageInfoSize;
+  UINT32                                        FmpImageInfoDescriptorVer;
+  UINT8                                         FmpImageInfoCount;
+  UINTN                                         DescriptorSize;
+  UINT32                                        PackageVersion;
+  CHAR16                                        *PackageVersionName;
+  UINT32                                        PackageVersionNameMaxLen;
+  UINT64                                        AttributesSupported;
+  UINT64                                        AttributesSetting;
+
+  Print(L"############\n");
+  Print(L"# FMP DATA #\n");
+  Print(L"############\n");
+  Status = gBS->LocateHandleBuffer (
+                  ByProtocol,
+                  &gEfiFirmwareManagementProtocolGuid,
+                  NULL,
+                  &NumberOfHandles,
+                  &HandleBuffer
+                  );
+  if (EFI_ERROR(Status)) {
+    Print(L"FMP protocol - %r\n", EFI_NOT_FOUND);
+    return;
+  }
+
+  for (Index = 0; Index < NumberOfHandles; Index++) {
+    Status = gBS->HandleProtocol(
+                    HandleBuffer[Index],
+                    &gEfiFirmwareManagementProtocolGuid,
+                    (VOID **)&Fmp
+                    );
+    if (EFI_ERROR(Status)) {
+      continue;
+    }
+
+    ImageInfoSize = 0;
+    Status = Fmp->GetImageInfo (
+                    Fmp,
+                    &ImageInfoSize,
+                    NULL,
+                    NULL,
+                    NULL,
+                    NULL,
+                    NULL,
+                    NULL
+                    );
+    if (Status != EFI_BUFFER_TOO_SMALL) {
+      continue;
+    }
+
+    FmpImageInfoBuf = NULL;
+    FmpImageInfoBuf = AllocateZeroPool (ImageInfoSize);
+    if (FmpImageInfoBuf == NULL) {
+      Status = EFI_OUT_OF_RESOURCES;
+      goto EXIT;
+    }
+
+    PackageVersionName = NULL;
+    Status = Fmp->GetImageInfo (
+                    Fmp,
+                    &ImageInfoSize,               // ImageInfoSize
+                    FmpImageInfoBuf,              // ImageInfo
+                    &FmpImageInfoDescriptorVer,   // DescriptorVersion
+                    &FmpImageInfoCount,           // DescriptorCount
+                    &DescriptorSize,              // DescriptorSize
+                    &PackageVersion,              // PackageVersion
+                    &PackageVersionName           // PackageVersionName
+                    );
+
+    //
+    // If FMP GetInformation interface failed, skip this resource
+    //
+    if (EFI_ERROR(Status)) {
+      Print(L"FMP (%d) ImageInfo - %r\n", Index, Status);
+      FreePool(FmpImageInfoBuf);
+      continue;
+    }
+
+    Print(L"FMP (%d) ImageInfo:\n", Index);
+    DumpFmpImageInfo(
+      ImageInfoSize,               // ImageInfoSize
+      FmpImageInfoBuf,             // ImageInfo
+      FmpImageInfoDescriptorVer,   // DescriptorVersion
+      FmpImageInfoCount,           // DescriptorCount
+      DescriptorSize,              // DescriptorSize
+      PackageVersion,              // PackageVersion
+      PackageVersionName           // PackageVersionName
+      );
+
+    if (PackageVersionName != NULL) {
+      FreePool(PackageVersionName);
+    }
+    FreePool(FmpImageInfoBuf);
+
+    //
+    // Get package info
+    //
+    PackageVersionName = NULL;
+    Status = Fmp->GetPackageInfo (
+                    Fmp,
+                    &PackageVersion,              // PackageVersion
+                    &PackageVersionName,          // PackageVersionName
+                    &PackageVersionNameMaxLen,    // PackageVersionNameMaxLen
+                    &AttributesSupported,         // AttributesSupported
+                    &AttributesSetting            // AttributesSetting
+                    );
+    if (EFI_ERROR(Status)) {
+      Print(L"FMP (%d) PackageInfo - %r\n", Index, Status);
+    } else {
+      Print(L"FMP (%d) ImageInfo:\n", Index);
+      DumpFmpPackageInfo(
+        PackageVersion,              // PackageVersion
+        PackageVersionName,          // PackageVersionName
+        PackageVersionNameMaxLen,    // PackageVersionNameMaxLen
+        AttributesSupported,         // AttributesSupported
+        AttributesSetting            // AttributesSetting
+        );
+
+      if (PackageVersionName != NULL) {
+        FreePool(PackageVersionName);
+      }
+    }
+  }
+  Print(L"\n");
+
+EXIT:
+  FreePool(HandleBuffer);
+}
-- 
2.7.4.windows.1



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

* [PATCH 18/45] MdeModulePkg/MdeModulePkg.dsc: Add capsule related component.
  2016-09-21  6:44 [PATCH 00/45] Add capsule update and recovery sample Jiewen Yao
                   ` (16 preceding siblings ...)
  2016-09-21  6:44 ` [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application Jiewen Yao
@ 2016-09-21  6:44 ` Jiewen Yao
  2016-09-21  6:45 ` [PATCH 19/45] IntelFrameworkModulePkg/DxeCapsuleLib: Add ProcessCapsules() interface Jiewen Yao
                   ` (30 subsequent siblings)
  48 siblings, 0 replies; 83+ messages in thread
From: Jiewen Yao @ 2016-09-21  6:44 UTC (permalink / raw)
  To: edk2-devel; +Cc: Feng Tian, Star Zeng, Michael D Kinney, Liming Gao, Chao Zhang

Add capsule related component to check build.

Cc: Feng Tian <feng.tian@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Chao Zhang <chao.b.zhang@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
---
 MdeModulePkg/MdeModulePkg.dsc | 24 ++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/MdeModulePkg/MdeModulePkg.dsc b/MdeModulePkg/MdeModulePkg.dsc
index 05120c7..2195b84 100644
--- a/MdeModulePkg/MdeModulePkg.dsc
+++ b/MdeModulePkg/MdeModulePkg.dsc
@@ -103,6 +103,11 @@
   VarCheckLib|MdeModulePkg/Library/VarCheckLib/VarCheckLib.inf
   FileExplorerLib|MdeModulePkg/Library/FileExplorerLib/FileExplorerLib.inf
 
+  EdkiiSystemCapsuleLib|MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.inf
+  FmpAuthenticationLib|MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.inf
+  IniParsingLib|MdeModulePkg/Library/IniParsingLib/IniParsingLib.inf
+  PlatformFlashAccessLib|MdeModulePkg/Library/PlatformFlashAccessLibNull/PlatformFlashAccessLibNull.inf
+
 [LibraryClasses.EBC.PEIM]
   IoLib|MdePkg/Library/PeiIoLibCpuIo/PeiIoLibCpuIo.inf
 
@@ -126,12 +131,14 @@
   LockBoxLib|MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxDxeLib.inf
   MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
   ExtractGuidedSectionLib|MdePkg/Library/DxeExtractGuidedSectionLib/DxeExtractGuidedSectionLib.inf
+  CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.inf
 
 [LibraryClasses.common.DXE_RUNTIME_DRIVER]
   HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
   MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
   DebugLib|MdePkg/Library/UefiDebugLibConOut/UefiDebugLibConOut.inf
   LockBoxLib|MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxDxeLib.inf
+  CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf
 
 [LibraryClasses.common.SMM_CORE]
   HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
@@ -158,6 +165,7 @@
   HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
   MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
   DebugLib|MdePkg/Library/UefiDebugLibStdErr/UefiDebugLibStdErr.inf
+  CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.inf
 
 [LibraryClasses.ARM, LibraryClasses.AARCH64]
   #
@@ -187,6 +195,9 @@
 [PcdsFixedAtBuild.IPF]
   gEfiMdePkgTokenSpaceGuid.PcdIoBlockBaseAddressForIpf|0x0ffffc000000
 
+[PcdsDynamicExDefault]
+  gEfiMdeModulePkgTokenSpaceGuid.PcdEdkiiSystemFirmwareImageDescriptor|{0x0}|VOID*|0x100
+
 ###################################################################################################
 #
 # Components Section - list of the modules and components that will be processed by compilation
@@ -408,6 +419,19 @@
   MdeModulePkg/Universal/SerialDxe/SerialDxe.inf
   MdeModulePkg/Universal/LoadFileOnFv2/LoadFileOnFv2.inf
 
+  MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf
+
+  MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.inf
+  MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.inf
+  MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.inf
+  MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf
+
+  MdeModulePkg/Library/IniParsingLib/IniParsingLib.inf
+
+  MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxe.inf
+  MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxe.inf
+  MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPei.inf
+
 [Components.IA32, Components.X64, Components.IPF]  
   MdeModulePkg/Universal/Network/UefiPxeBcDxe/UefiPxeBcDxe.inf
   MdeModulePkg/Universal/DebugSupportDxe/DebugSupportDxe.inf
-- 
2.7.4.windows.1



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

* [PATCH 19/45] IntelFrameworkModulePkg/DxeCapsuleLib: Add ProcessCapsules() interface.
  2016-09-21  6:44 [PATCH 00/45] Add capsule update and recovery sample Jiewen Yao
                   ` (17 preceding siblings ...)
  2016-09-21  6:44 ` [PATCH 18/45] MdeModulePkg/MdeModulePkg.dsc: Add capsule related component Jiewen Yao
@ 2016-09-21  6:45 ` Jiewen Yao
  2016-09-28  8:08   ` Fan, Jeff
  2016-09-21  6:45 ` [PATCH 20/45] SecurityPkg/SecurityPkg.dec: Add PcdPkcs7CertBuffer PCD Jiewen Yao
                   ` (29 subsequent siblings)
  48 siblings, 1 reply; 83+ messages in thread
From: Jiewen Yao @ 2016-09-21  6:45 UTC (permalink / raw)
  To: edk2-devel
  Cc: Jeff Fan, Feng Tian, Star Zeng, Michael D Kinney, Liming Gao,
	Chao Zhang

Add NULL ProcessCapsules() interface for DxeCapsuleLib.
IntelFrameworkModulePkg is under maintenance phase.
We stop adding new feature there.
Just add NULL function to make it pass build.

Cc: Jeff Fan <jeff.fan@intel.com>
Cc: Feng Tian <feng.tian@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Chao Zhang <chao.b.zhang@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
---
 IntelFrameworkModulePkg/Library/DxeCapsuleLib/DxeCapsuleLib.c | 39 +++++++++++++++++++-
 1 file changed, 38 insertions(+), 1 deletion(-)

diff --git a/IntelFrameworkModulePkg/Library/DxeCapsuleLib/DxeCapsuleLib.c b/IntelFrameworkModulePkg/Library/DxeCapsuleLib/DxeCapsuleLib.c
index fc9b533..c964b2d 100644
--- a/IntelFrameworkModulePkg/Library/DxeCapsuleLib/DxeCapsuleLib.c
+++ b/IntelFrameworkModulePkg/Library/DxeCapsuleLib/DxeCapsuleLib.c
@@ -1,7 +1,7 @@
 /** @file
   Capsule Library instance to process capsule images.
 
-  Copyright (c) 2007 - 2013, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2007 - 2016, Intel Corporation. All rights reserved.<BR>
 
   This program and the accompanying materials
   are licensed and made available under the terms and conditions of the BSD License
@@ -515,4 +515,41 @@ ProcessCapsuleImage (
   return Status;
 }
 
+/**
+
+  This routine is called to process capsules.
+
+  Caution: This function may receive untrusted input.
+
+  If the current boot mode is NOT BOOT_ON_FLASH_UPDATE, this routine does nothing.
+  If the current boot mode is BOOT_ON_FLASH_UPDATE, the capsules reported in
+  EFI_HOB_UEFI_CAPSULE are processed. If there is no EFI_HOB_UEFI_CAPSULE, this
+  routine does nothing.
+
+  This routine should be called twice in BDS.
+  1) The first call must be before EndOfDxe. The system capsules is processed.
+     If device capsule FMP protocols are exposted at this time and device FMP
+     capsule has zero EmbeddedDriverCount, the device capsules are processed.
+     Each individual capsule result is recorded in capsule record variable.
+     System may reset in this function, if reset is required by capsule.
+
+  2) The second call must be after EndOfDxe and after ConnectAll, so that all
+     device capsule FMP protocols are exposed.
+     The system capsules are skipped. If the device capsules are NOT processed
+     in first call, they are processed here.
+     Each individual capsule result is recorded in capsule record variable.
+     System may reset in this function, if reset is required by capsule.
+
+  @retval EFI_SUCCESS             There is no error when processing capsules.
+  @retval EFI_OUT_OF_RESOURCES    No enough resource to process capsules.
+
+**/
+EFI_STATUS
+EFIAPI
+ProcessCapsules(
+  VOID
+  )
+{
+  return EFI_UNSUPPORTED;
+}
 
-- 
2.7.4.windows.1



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

* [PATCH 20/45] SecurityPkg/SecurityPkg.dec: Add PcdPkcs7CertBuffer PCD.
  2016-09-21  6:44 [PATCH 00/45] Add capsule update and recovery sample Jiewen Yao
                   ` (18 preceding siblings ...)
  2016-09-21  6:45 ` [PATCH 19/45] IntelFrameworkModulePkg/DxeCapsuleLib: Add ProcessCapsules() interface Jiewen Yao
@ 2016-09-21  6:45 ` Jiewen Yao
  2016-09-21  6:45 ` [PATCH 21/45] SecurityPkg/FmpAuthenticationPkcs7Lib: Add PKCS7 NULL class for FMP Jiewen Yao
                   ` (28 subsequent siblings)
  48 siblings, 0 replies; 83+ messages in thread
From: Jiewen Yao @ 2016-09-21  6:45 UTC (permalink / raw)
  To: edk2-devel; +Cc: Feng Tian, Star Zeng, Michael D Kinney, Liming Gao, Chao Zhang

This PCD is similar to PcdRsa2048Sha256PublicKeyBuffer.
It provides trusted cert for PKCS7 verification.
It can be used for Recovery and Capsule Update images.

Cc: Feng Tian <feng.tian@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Chao Zhang <chao.b.zhang@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
---
 SecurityPkg/SecurityPkg.dec | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/SecurityPkg/SecurityPkg.dec b/SecurityPkg/SecurityPkg.dec
index f4f4d19..156fc48 100644
--- a/SecurityPkg/SecurityPkg.dec
+++ b/SecurityPkg/SecurityPkg.dec
@@ -405,6 +405,12 @@
   #
   gEfiSecurityPkgTokenSpaceGuid.PcdRsa2048Sha256PublicKeyBuffer|{0x91, 0x29, 0xc4, 0xbd, 0xea, 0x6d, 0xda, 0xb3, 0xaa, 0x6f, 0x50, 0x16, 0xfc, 0xdb, 0x4b, 0x7e, 0x3c, 0xd6, 0xdc, 0xa4, 0x7a, 0x0e, 0xdd, 0xe6, 0x15, 0x8c, 0x73, 0x96, 0xa2, 0xd4, 0xa6, 0x4d}|VOID*|0x00010013
 
+  ## Provides one PKCS7 cert used to verify Recovery and Capsule Update images
+  #
+  # @Prompt One PKCS7 cert used to verify Recovery and Capsule Update images
+  #
+  gEfiSecurityPkgTokenSpaceGuid.PcdPkcs7CertBuffer|{0x30, 0x82, 0x02, 0xf0, 0x30, 0x82, 0x01, 0xdc, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x34, 0x30, 0x27, 0x7f, 0x05, 0x3d, 0x95, 0x85, 0x43, 0xa0, 0xa4, 0xf5, 0x0c, 0x9a, 0xe7, 0xca, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d, 0x05, 0x00, 0x30, 0x13, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x08, 0x54, 0x65, 0x73, 0x74, 0x52, 0x6f, 0x6f, 0x74, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x36, 0x30, 0x38, 0x30, 0x34, 0x31, 0x35, 0x30, 0x31, 0x34, 0x38, 0x5a, 0x17, 0x0d, 0x33, 0x39, 0x31, 0x32, 0x33, 0x31, 0x32, 0x33, 0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x13, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x08, 0x54, 0x65, 0x73, 0x74, 0x52, 0x6f, 0x6f, 0x74, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0x94, 0xe6, 0x33, 0x4f, 0x56, 0xc3, 0x07, 0xa0, 0xd0, 0x99, 0x57, 0xc3, 0xe1, 0x56, 0x42, 0x01, 0x70, 0x59, 0x1c, 0x2f, 0x4a, 0x66, 0x8f, 0x34, 0x9e, 0x93, 0xbd, 0xb6, 0xec, 0x92, 0xa4, 0x90, 0x51, 0x5d, 0xc6, 0x8f, 0xb5, 0xc3, 0x86, 0x15, 0xdf, 0x60, 0x80, 0xbe, 0xb8, 0x78, 0x59, 0x5b, 0x9b, 0xfd, 0x27, 0x92, 0x69, 0xcc, 0xca, 0x8e, 0x3e, 0x9e, 0x81, 0x47, 0x5b, 0x84, 0xef, 0x5c, 0x9b, 0xb3, 0x4a, 0x43, 0x5b, 0x8d, 0x0b, 0x31, 0x04, 0x00, 0xb6, 0x8a, 0xc0, 0xa9, 0xf5, 0x21, 0xd0, 0x3f, 0xcd, 0xb0, 0x67, 0x7d, 0x50, 0x33, 0x2e, 0xfb, 0x1b, 0x2c, 0x16, 0x2e, 0xee, 0x56, 0x01, 0x87, 0xf6, 0xc8, 0xd4, 0x53, 0x07, 0x67, 0x99, 0x0b, 0x46, 0xbf, 0x1d, 0x90, 0xc6, 0xdb, 0x7f, 0x6d, 0x62, 0x0c, 0x4a, 0xac, 0xa8, 0xa2, 0x3c, 0x79, 0x0f, 0xad, 0x8f, 0xfe, 0xc1, 0xe8, 0xe5, 0x27, 0x3d, 0xf9, 0xa6, 0x9a, 0x1d, 0xec, 0x9a, 0x5f, 0x62, 0x51, 0x2e, 0x98, 0x1d, 0x29, 0xba, 0x6b, 0x8a, 0xfb, 0x43, 0x0e, 0x68, 0x29, 0xf5, 0xbe, 0x67, 0x48, 0x44, 0x28, 0x45, 0xfe, 0x1d, 0x3b, 0x50, 0x72, 0x6a, 0xc0, 0xbb, 0x0c, 0x9f, 0x02, 0x61, 0xad, 0x63, 0xa7, 0x87, 0xf6, 0x32, 0x9f, 0x3e, 0x16, 0x5c, 0xee, 0xcc, 0x05, 0xbd, 0x17, 0xe8, 0x46, 0x52, 0xaf, 0x50, 0x8a, 0xa6, 0x7e, 0x16, 0x69, 0x83, 0x69, 0x5b, 0x6e, 0x4d, 0xc7, 0xcf, 0x80, 0xb8, 0xcd, 0xf6, 0x66, 0x3f, 0xbe, 0x6c, 0xa0, 0xe8, 0x9c, 0x26, 0x60, 0xba, 0xa9, 0x05, 0xdd, 0x71, 0x4a, 0xbd, 0x00, 0xa8, 0x0c, 0xf7, 0x50, 0xab, 0x44, 0xd6, 0x3e, 0x87, 0x21, 0x3c, 0x2d, 0xe6, 0x33, 0x27, 0x5e, 0x21, 0x27, 0xb9, 0xdc, 0x38, 0x48, 0xd6, 0x3a, 0x96, 0xe1, 0x17, 0x47, 0x65, 0x65, 0xce, 0x3d, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x48, 0x30, 0x46, 0x30, 0x44, 0x06, 0x03, 0x55, 0x1d, 0x01, 0x04, 0x3d, 0x30, 0x3b, 0x80, 0x10, 0xce, 0xb5, 0x7a, 0xcf, 0xe5, 0x21, 0xc7, 0x6b, 0xf3, 0xec, 0x92, 0xd4, 0xbf, 0x65, 0x2a, 0x35, 0xa1, 0x15, 0x30, 0x13, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x08, 0x54, 0x65, 0x73, 0x74, 0x52, 0x6f, 0x6f, 0x74, 0x82, 0x10, 0x34, 0x30, 0x27, 0x7f, 0x05, 0x3d, 0x95, 0x85, 0x43, 0xa0, 0xa4, 0xf5, 0x0c, 0x9a, 0xe7, 0xca, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x6b, 0x0d, 0xe0, 0x0a, 0xd0, 0xee, 0x5b, 0x3f, 0xb6, 0x73, 0x48, 0x62, 0xe8, 0xf4, 0x5b, 0xe1, 0xed, 0xd9, 0x00, 0xc5, 0xe5, 0x0e, 0x68, 0xfb, 0x53, 0x33, 0x30, 0x6a, 0x60, 0xba, 0xee, 0x38, 0x5b, 0x51, 0x63, 0x70, 0xd5, 0x7e, 0x05, 0xfe, 0xe4, 0x45, 0x2a, 0x15, 0x62, 0x1b, 0xfc, 0xd8, 0x75, 0x93, 0x56, 0xf6, 0xe6, 0x06, 0x85, 0x21, 0xf7, 0x08, 0x47, 0x26, 0xb9, 0xfe, 0x05, 0x4e, 0x90, 0x22, 0x54, 0xf4, 0x39, 0x09, 0x4c, 0x5c, 0x8e, 0xcd, 0x7c, 0x3b, 0xaf, 0x4b, 0x2d, 0x18, 0x06, 0xf4, 0x5c, 0x24, 0x2a, 0x64, 0xf7, 0x59, 0x75, 0x28, 0x97, 0xa9, 0x90, 0x2c, 0xba, 0x46, 0x02, 0x6a, 0x64, 0x66, 0x49, 0x32, 0xcb, 0x5d, 0x34, 0xfe, 0x24, 0xe4, 0x44, 0xb0, 0xc2, 0xad, 0x17, 0x1b, 0x05, 0x7d, 0xd3, 0x58, 0x88, 0x2e, 0xbe, 0x0e, 0xd7, 0x2b, 0xca, 0x5c, 0xbf, 0x28, 0x25, 0x3d, 0xd8, 0xbb, 0x3c, 0x38, 0x52, 0xe6, 0x27, 0xfa, 0xd2, 0xb8, 0x45, 0x6b, 0x5f, 0x7f, 0x4b, 0xb0, 0x23, 0x05, 0xe8, 0xaf, 0x67, 0xe8, 0xe2, 0x6c, 0x2f, 0x9f, 0xf8, 0x73, 0x7f, 0xc3, 0x17, 0xbc, 0xb2, 0x6a, 0x5b, 0x2a, 0xf3, 0x6b, 0xd3, 0xdc, 0x7f, 0xdf, 0x2f, 0xd0, 0xab, 0x06, 0x0c, 0xfe, 0x03, 0xe7, 0x8d, 0x82, 0xec, 0x84, 0x3d, 0xc8, 0x7d, 0xed, 0xcb, 0x6a, 0x5b, 0x35, 0x48, 0x55, 0x07, 0xfb, 0xaa, 0x78, 0x1a, 0x01, 0xbb, 0x98, 0x45, 0x8b, 0xda, 0x8a, 0xe3, 0x21, 0x57, 0x86, 0x15, 0x23, 0x17, 0x50, 0x1b, 0x9c, 0xbc, 0x1a, 0x59, 0xa8, 0x2a, 0xad, 0x3a, 0x7e, 0x01, 0x24, 0x83, 0xf7, 0xb0, 0x61, 0xe6, 0xbd, 0x4f, 0xd9, 0x91, 0x90, 0xa7, 0x2a, 0xb9, 0x0c, 0x3b, 0xab, 0x95, 0x20, 0x1c, 0xf0, 0x74, 0xce, 0x02, 0xba, 0x14, 0x5d, 0xf1, 0x91, 0x25, 0x4a,}|VOID*|0x00010014
+
   ## This PCD defines minimum length(in bytes) of the system preboot TCG event log area(LAML).
   #  For PC Client Implementation spec up to and including 1.2 the minimum log size is 64KB.
   # @Prompt Minimum length(in bytes) of the system preboot TCG event log area(LAML).
-- 
2.7.4.windows.1



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

* [PATCH 21/45] SecurityPkg/FmpAuthenticationPkcs7Lib: Add PKCS7 NULL class for FMP.
  2016-09-21  6:44 [PATCH 00/45] Add capsule update and recovery sample Jiewen Yao
                   ` (19 preceding siblings ...)
  2016-09-21  6:45 ` [PATCH 20/45] SecurityPkg/SecurityPkg.dec: Add PcdPkcs7CertBuffer PCD Jiewen Yao
@ 2016-09-21  6:45 ` Jiewen Yao
  2016-09-21  6:45 ` [PATCH 22/45] SecurityPkg/FmpAuthenticationRsa2048Sha256Lib: Add " Jiewen Yao
                   ` (27 subsequent siblings)
  48 siblings, 0 replies; 83+ messages in thread
From: Jiewen Yao @ 2016-09-21  6:45 UTC (permalink / raw)
  To: edk2-devel; +Cc: Feng Tian, Star Zeng, Michael D Kinney, Liming Gao, Chao Zhang

This is a NULL class for FmpAuthenticationLib. It provides PKCS7 based
FMP authentication.

Cc: Feng Tian <feng.tian@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Chao Zhang <chao.b.zhang@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
---
 SecurityPkg/Library/FmpAuthenticationPkcs7Lib/FmpAuthenticationPkcs7Lib.c   | 144 ++++++++++++++++++++
 SecurityPkg/Library/FmpAuthenticationPkcs7Lib/FmpAuthenticationPkcs7Lib.inf |  52 +++++++
 SecurityPkg/Library/FmpAuthenticationPkcs7Lib/FmpAuthenticationPkcs7Lib.uni |  26 ++++
 3 files changed, 222 insertions(+)

diff --git a/SecurityPkg/Library/FmpAuthenticationPkcs7Lib/FmpAuthenticationPkcs7Lib.c b/SecurityPkg/Library/FmpAuthenticationPkcs7Lib/FmpAuthenticationPkcs7Lib.c
new file mode 100644
index 0000000..6a81d9f
--- /dev/null
+++ b/SecurityPkg/Library/FmpAuthenticationPkcs7Lib/FmpAuthenticationPkcs7Lib.c
@@ -0,0 +1,144 @@
+/** @file
+  FMP Authentication PKCS7 handler.
+
+  Caution: This module requires additional review when modified.
+  This module will have external input - capsule image.
+  This external input must be validated carefully to avoid security issue like
+  buffer overflow, integer overflow.
+
+  FmpAuthenticatedHandlerPkcs7() will receive untrusted input and do basic
+  validation.
+
+  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Uefi.h>
+
+#include <Guid/SystemResourceTable.h>
+#include <Guid/FirmwareContentsSigned.h>
+#include <Guid/WinCertificate.h>
+#include <Guid/EdkiiSystemFmpCapsule.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/BaseCryptLib.h>
+#include <Library/FmpAuthenticationLib.h>
+
+#include <Protocol/FirmwareManagement.h>
+
+STATIC UINT8 *mPkcs7Cert;
+STATIC UINTN mPkcs7CertSize;
+
+/**
+  The handler is used to do the authentication for FMP capsule based upon
+  EFI_FIRMWARE_IMAGE_AUTHENTICATION.
+
+  Caution: This function may receive untrusted input.
+
+  @param[in]    Image              Points to the new FMP authentication image,
+                                   start from EFI_FIRMWARE_IMAGE_AUTHENTICATION.
+  @param[in]    ImageSize          Size of the authentication image in bytes.
+  @param[out]   LastAttemptStatus  The last attempt status, which will be recorded
+                                   in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+
+  @retval RETURN_SUCCESS            Authentication pass.
+  @retval RETURN_SECURITY_VIOLATION Authentication fail.
+                                    The detail reson is recorded in LastAttemptStatus.
+**/
+RETURN_STATUS
+EFIAPI
+FmpAuthenticatedHandlerPkcs7(
+  IN VOID                         *Image,
+  IN UINTN                        ImageSize,
+  OUT UINT32                      *LastAttemptStatus
+  )
+{
+  RETURN_STATUS                             Status;
+  EFI_FIRMWARE_IMAGE_AUTHENTICATION         *ImageAuthentication;
+  BOOLEAN                                   CryptoStatus;
+  VOID                                      *P7Data;
+  UINTN                                     P7Length;
+  UINTN                                     ImageOffset;
+  UINT64                                    MonotonicCount;
+  UINT64                                    Backup;
+
+  DEBUG((DEBUG_INFO, "FmpAuthenticatedHandlerPkcs7 - Image: 0x%08x - 0x%08x\n", (UINTN)Image, (UINTN)ImageSize));
+
+  ImageAuthentication = (EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image;
+  MonotonicCount = ImageAuthentication->MonotonicCount;
+  ImageOffset = ImageAuthentication->AuthInfo.Hdr.dwLength;
+  P7Length = ImageAuthentication->AuthInfo.Hdr.dwLength - (sizeof(WIN_CERTIFICATE) + sizeof(EFI_GUID));
+  P7Data = AllocateCopyPool (P7Length, ImageAuthentication->AuthInfo.CertData);
+  if (P7Data == NULL) {
+    //
+    // If PKCS7 signature verification fails, AUTH tested failed bit is set.
+    //
+    DEBUG((DEBUG_ERROR, "FmpAuthenticatedHandlerPkcs7: P7Data == NULL\n"));
+    *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INSUFFICIENT_RESOURCES;
+    Status = RETURN_OUT_OF_RESOURCES;
+    goto Done;
+  }
+
+  // It is a signature across the variable data and the Monotonic Count value.
+  CopyMem(&Backup, (UINT8 *)Image + ImageOffset, sizeof(Backup));
+  CopyMem((UINT8 *)Image + ImageOffset, &MonotonicCount, sizeof(MonotonicCount));
+  CryptoStatus = Pkcs7Verify(
+                   P7Data,
+                   P7Length,
+                   mPkcs7Cert,
+                   mPkcs7CertSize,
+                   (UINT8 *)Image + ImageOffset,
+                   ImageSize - ImageOffset
+                   );
+  CopyMem((UINT8 *)Image + ImageOffset, &Backup, sizeof(Backup));
+  FreePool(P7Data);
+  if (!CryptoStatus) {
+    //
+    // If PKCS7 signature verification fails, AUTH tested failed bit is set.
+    //
+    DEBUG((DEBUG_ERROR, "FmpAuthenticatedHandlerPkcs7: Pkcs7Verify() failed\n"));
+    *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_AUTH_ERROR;
+    Status = RETURN_SECURITY_VIOLATION;
+    goto Done;
+  }
+  DEBUG((DEBUG_INFO, "FmpAuthenticatedHandlerPkcs7: PASS verification\n"));
+
+  *LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;
+  Status = RETURN_SUCCESS;
+
+Done:
+  return Status;
+}
+
+/**
+  The constructor function to register FMP authentication handler.
+
+  @retval RETURN_SUCCESS   The constructor successfully .
+**/
+RETURN_STATUS
+EFIAPI
+FmpAuthenticationPkcs7LibConstructor(
+  VOID
+  )
+{
+  RETURN_STATUS  Status;
+
+  mPkcs7CertSize = PcdGetSize(PcdPkcs7CertBuffer);
+  mPkcs7Cert = AllocateCopyPool(mPkcs7CertSize, PcdGetPtr(PcdPkcs7CertBuffer));
+  ASSERT(mPkcs7Cert != NULL);
+
+  Status = RegisterFmpAuthenticationHandler(&gEfiCertPkcs7Guid, FmpAuthenticatedHandlerPkcs7);
+  ASSERT_EFI_ERROR(Status);
+
+  return RETURN_SUCCESS;
+}
diff --git a/SecurityPkg/Library/FmpAuthenticationPkcs7Lib/FmpAuthenticationPkcs7Lib.inf b/SecurityPkg/Library/FmpAuthenticationPkcs7Lib/FmpAuthenticationPkcs7Lib.inf
new file mode 100644
index 0000000..99fa2be
--- /dev/null
+++ b/SecurityPkg/Library/FmpAuthenticationPkcs7Lib/FmpAuthenticationPkcs7Lib.inf
@@ -0,0 +1,52 @@
+## @file
+#  FMP Authentication PKCS7 handler.
+#
+#  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = FmpAuthenticationPkcs7Lib
+  MODULE_UNI_FILE                = FmpAuthenticationPkcs7Lib.uni
+  FILE_GUID                      = F4EA205B-7345-452C-9D62-53BA6F3B8910
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = NULL
+  CONSTRUCTOR                    = FmpAuthenticationPkcs7LibConstructor
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64 IPF EBC
+#
+
+[Sources]
+  FmpAuthenticationPkcs7Lib.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  SecurityPkg/SecurityPkg.dec
+  CryptoPkg/CryptoPkg.dec
+
+[LibraryClasses]
+  BaseLib
+  BaseMemoryLib
+  DebugLib
+  MemoryAllocationLib
+  BaseCryptLib
+  FmpAuthenticationLib
+
+[Pcd]
+  gEfiSecurityPkgTokenSpaceGuid.PcdPkcs7CertBuffer
+
+[Guids]
+  gEfiCertPkcs7Guid
diff --git a/SecurityPkg/Library/FmpAuthenticationPkcs7Lib/FmpAuthenticationPkcs7Lib.uni b/SecurityPkg/Library/FmpAuthenticationPkcs7Lib/FmpAuthenticationPkcs7Lib.uni
new file mode 100644
index 0000000..d327e53
--- /dev/null
+++ b/SecurityPkg/Library/FmpAuthenticationPkcs7Lib/FmpAuthenticationPkcs7Lib.uni
@@ -0,0 +1,26 @@
+// /** @file
+// FMP Authentication PKCS7 handler.
+//
+// This library provide FMP Authentication PKCS7 handler to verify EFI_FIRMWARE_IMAGE_AUTHENTICATION.
+//
+// Caution: This module requires additional review when modified.
+// This library will have external input - capsule image.
+// This external input must be validated carefully to avoid security issues such as
+// buffer overflow or integer overflow.
+//
+// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+//
+// This program and the accompanying materials
+// are licensed and made available under the terms and conditions of the BSD License
+// which accompanies this distribution. The full text of the license may be found at
+// http://opensource.org/licenses/bsd-license.php
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT             #language en-US "FMP Authentication PKCS7 handler."
+
+#string STR_MODULE_DESCRIPTION          #language en-US "This library provide FMP Authentication PKCS7 handler to verify EFI_FIRMWARE_IMAGE_AUTHENTICATION."
+
-- 
2.7.4.windows.1



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

* [PATCH 22/45] SecurityPkg/FmpAuthenticationRsa2048Sha256Lib: Add NULL class for FMP.
  2016-09-21  6:44 [PATCH 00/45] Add capsule update and recovery sample Jiewen Yao
                   ` (20 preceding siblings ...)
  2016-09-21  6:45 ` [PATCH 21/45] SecurityPkg/FmpAuthenticationPkcs7Lib: Add PKCS7 NULL class for FMP Jiewen Yao
@ 2016-09-21  6:45 ` Jiewen Yao
  2016-09-21  6:45 ` [PATCH 23/45] SecurityPkg/SecurityPkg.dsc: Add FmpAuthentication*Lib Jiewen Yao
                   ` (26 subsequent siblings)
  48 siblings, 0 replies; 83+ messages in thread
From: Jiewen Yao @ 2016-09-21  6:45 UTC (permalink / raw)
  To: edk2-devel; +Cc: Feng Tian, Star Zeng, Michael D Kinney, Liming Gao, Chao Zhang

This is a NULL class for FmpAuthenticationLib. It provides Rsa2048Sha256
based FMP authentication.

Cc: Feng Tian <feng.tian@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Chao Zhang <chao.b.zhang@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
---
 SecurityPkg/Library/FmpAuthenticationRsa2048Sha256Lib/FmpAuthenticationRsa2048Sha256Lib.c   | 286 ++++++++++++++++++++
 SecurityPkg/Library/FmpAuthenticationRsa2048Sha256Lib/FmpAuthenticationRsa2048Sha256Lib.inf |  53 ++++
 SecurityPkg/Library/FmpAuthenticationRsa2048Sha256Lib/FmpAuthenticationRsa2048Sha256Lib.uni |  26 ++
 3 files changed, 365 insertions(+)

diff --git a/SecurityPkg/Library/FmpAuthenticationRsa2048Sha256Lib/FmpAuthenticationRsa2048Sha256Lib.c b/SecurityPkg/Library/FmpAuthenticationRsa2048Sha256Lib/FmpAuthenticationRsa2048Sha256Lib.c
new file mode 100644
index 0000000..3a9c75f
--- /dev/null
+++ b/SecurityPkg/Library/FmpAuthenticationRsa2048Sha256Lib/FmpAuthenticationRsa2048Sha256Lib.c
@@ -0,0 +1,286 @@
+/** @file
+  FMP Authentication RSA2048SHA256 handler.
+
+  Caution: This module requires additional review when modified.
+  This module will have external input - capsule image.
+  This external input must be validated carefully to avoid security issue like
+  buffer overflow, integer overflow.
+
+  FmpAuthenticatedHandlerRsa2048Sha256() will receive untrusted input and do basic
+  validation.
+
+  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Uefi.h>
+
+#include <Guid/SystemResourceTable.h>
+#include <Guid/FirmwareContentsSigned.h>
+#include <Guid/WinCertificate.h>
+#include <Guid/EdkiiSystemFmpCapsule.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/BaseCryptLib.h>
+#include <Library/FmpAuthenticationLib.h>
+
+#include <Protocol/FirmwareManagement.h>
+
+///
+/// Public Exponent of RSA Key.
+///
+STATIC CONST UINT8 mRsaE[] = { 0x01, 0x00, 0x01 };
+
+STATIC UINT8 *mPublicKey;
+STATIC UINTN mPublicKeyBufferSize;
+
+/**
+  The handler is used to do the authentication for FMP capsule based upon
+  EFI_FIRMWARE_IMAGE_AUTHENTICATION.
+
+  Caution: This function may receive untrusted input.
+
+  @param[in]    Image              Points to the new FMP authentication image,
+                                   start from EFI_FIRMWARE_IMAGE_AUTHENTICATION.
+  @param[in]    ImageSize          Size of the authentication image in bytes.
+  @param[out]   LastAttemptStatus  The last attempt status, which will be recorded
+                                   in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+
+  @retval RETURN_SUCCESS            Authentication pass.
+  @retval RETURN_SECURITY_VIOLATION Authentication fail.
+                                    The detail reson is recorded in LastAttemptStatus.
+**/
+RETURN_STATUS
+EFIAPI
+FmpAuthenticatedHandlerRsa2048Sha256(
+  IN VOID                         *Image,
+  IN UINTN                        ImageSize,
+  OUT UINT32                      *LastAttemptStatus
+  )
+{
+  RETURN_STATUS                             Status;
+  EFI_FIRMWARE_IMAGE_AUTHENTICATION         *ImageAuthentication;
+  EFI_CERT_BLOCK_RSA_2048_SHA256            *CertBlockRsa2048Sha256;
+  BOOLEAN                                   CryptoStatus;
+  UINT8                                     Digest[SHA256_DIGEST_SIZE];
+  UINT8                                     *PublicKey;
+  UINTN                                     PublicKeyBufferSize;
+  VOID                                      *HashContext;
+  VOID                                      *Rsa;
+  UINTN                                     ImageOffset;
+  UINT64                                    MonotonicCount;
+  UINT64                                    Backup;
+
+  DEBUG ((DEBUG_INFO, "FmpAuthenticatedHandlerRsa2048Sha256 - Image: 0x%08x - 0x%08x\n", (UINTN)Image, (UINTN)ImageSize));
+
+  ImageAuthentication = (EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image;
+  MonotonicCount = ImageAuthentication->MonotonicCount;
+  if (ImageAuthentication->AuthInfo.Hdr.dwLength != sizeof(WIN_CERTIFICATE) + sizeof(EFI_GUID) + sizeof(EFI_CERT_BLOCK_RSA_2048_SHA256)) {
+    DEBUG((DEBUG_ERROR, "FmpAuthenticatedHandlerRsa2048Sha256 - dwLength: 0x%04x, dwLength - 0x%04x\n", (UINTN)ImageAuthentication->AuthInfo.Hdr.dwLength, (UINTN)sizeof(WIN_CERTIFICATE) + sizeof(EFI_GUID) + sizeof(EFI_CERT_BLOCK_RSA_2048_SHA256)));
+    *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INVALID_FORMAT;
+    return RETURN_SECURITY_VIOLATION;
+  }
+  ImageOffset = ImageAuthentication->AuthInfo.Hdr.dwLength;
+
+  CertBlockRsa2048Sha256 = (EFI_CERT_BLOCK_RSA_2048_SHA256 *)ImageAuthentication->AuthInfo.CertData;
+  if (!CompareGuid(&CertBlockRsa2048Sha256->HashType, &gEfiHashAlgorithmSha256Guid)) {
+    DEBUG((DEBUG_ERROR, "FmpAuthenticatedHandlerRsa2048Sha256 - HashType: %g, expect - %g\n", &CertBlockRsa2048Sha256->HashType, &gEfiHashAlgorithmSha256Guid));
+    *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INVALID_FORMAT;
+    return RETURN_SECURITY_VIOLATION;
+  }
+
+  HashContext = NULL;
+  Rsa = NULL;
+
+  //
+  // Allocate hash context buffer required for SHA 256
+  //
+  HashContext = AllocatePool (Sha256GetContextSize ());
+  if (HashContext == NULL) {
+    CryptoStatus = FALSE;
+    DEBUG ((DEBUG_ERROR, "FmpAuthenticatedHandlerRsa2048Sha256: Can not allocate hash context\n"));
+    *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INSUFFICIENT_RESOURCES;
+    Status = RETURN_OUT_OF_RESOURCES;
+    goto Done;
+  }
+
+  //
+  // Hash public key from data payload with SHA256.
+  //
+  ZeroMem (Digest, SHA256_DIGEST_SIZE);
+  CryptoStatus = Sha256Init (HashContext);
+  if (!CryptoStatus) {
+    DEBUG ((DEBUG_ERROR, "FmpAuthenticatedHandlerRsa2048Sha256: Sha256Init() failed\n"));
+    *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INSUFFICIENT_RESOURCES;
+    Status = RETURN_OUT_OF_RESOURCES;
+    goto Done;
+  }
+  CryptoStatus = Sha256Update (HashContext, &CertBlockRsa2048Sha256->PublicKey, sizeof(CertBlockRsa2048Sha256->PublicKey));
+  if (!CryptoStatus) {
+    DEBUG ((DEBUG_ERROR, "FmpAuthenticatedHandlerRsa2048Sha256: Sha256Update() failed\n"));
+    *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INSUFFICIENT_RESOURCES;
+    Status = RETURN_OUT_OF_RESOURCES;
+    goto Done;
+  }
+  CryptoStatus  = Sha256Final (HashContext, Digest);
+  if (!CryptoStatus) {
+    DEBUG ((DEBUG_ERROR, "FmpAuthenticatedHandlerRsa2048Sha256: Sha256Final() failed\n"));
+    *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INSUFFICIENT_RESOURCES;
+    Status = RETURN_OUT_OF_RESOURCES;
+    goto Done;
+  }
+
+  //
+  // Fail if the PublicKey is not one of the public keys in PcdRsa2048Sha256PublicKeyBuffer
+  //
+  PublicKey = mPublicKey;
+  PublicKeyBufferSize = mPublicKeyBufferSize;
+  CryptoStatus = FALSE;
+  while (PublicKeyBufferSize != 0) {
+    if (CompareMem (Digest, PublicKey, SHA256_DIGEST_SIZE) == 0) {
+      CryptoStatus = TRUE;
+      break;
+    }
+    PublicKey = PublicKey + SHA256_DIGEST_SIZE;
+    PublicKeyBufferSize = PublicKeyBufferSize - SHA256_DIGEST_SIZE;
+  }
+  if (!CryptoStatus) {
+    DEBUG ((DEBUG_ERROR, "FmpAuthenticatedHandlerRsa2048Sha256: Public key in section is not supported\n"));
+    *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_AUTH_ERROR;
+    Status = RETURN_SECURITY_VIOLATION;
+    goto Done;
+  }
+
+  //
+  // Generate & Initialize RSA Context.
+  //
+  Rsa = RsaNew ();
+  if (Rsa == NULL) {
+    CryptoStatus = FALSE;
+    DEBUG ((DEBUG_ERROR, "FmpAuthenticatedHandlerRsa2048Sha256: RsaNew() failed\n"));
+    *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INSUFFICIENT_RESOURCES;
+    goto Done;
+  }
+
+  //
+  // Set RSA Key Components.
+  // NOTE: Only N and E are needed to be set as RSA public key for signature verification.
+  //
+  CryptoStatus = RsaSetKey (Rsa, RsaKeyN, CertBlockRsa2048Sha256->PublicKey, sizeof(CertBlockRsa2048Sha256->PublicKey));
+  if (!CryptoStatus) {
+    DEBUG ((DEBUG_ERROR, "FmpAuthenticatedHandlerRsa2048Sha256: RsaSetKey(RsaKeyN) failed\n"));
+    *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INSUFFICIENT_RESOURCES;
+    Status = RETURN_OUT_OF_RESOURCES;
+    goto Done;
+  }
+  CryptoStatus = RsaSetKey (Rsa, RsaKeyE, mRsaE, sizeof (mRsaE));
+  if (!CryptoStatus) {
+    DEBUG ((DEBUG_ERROR, "FmpAuthenticatedHandlerRsa2048Sha256: RsaSetKey(RsaKeyE) failed\n"));
+    *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INSUFFICIENT_RESOURCES;
+    Status = RETURN_OUT_OF_RESOURCES;
+    goto Done;
+  }
+
+  //
+  // Hash data payload with SHA256.
+  //
+  ZeroMem (Digest, SHA256_DIGEST_SIZE);
+  CryptoStatus = Sha256Init (HashContext);
+  if (!CryptoStatus) {
+    DEBUG ((DEBUG_ERROR, "FmpAuthenticatedHandlerRsa2048Sha256: Sha256Init() failed\n"));
+    *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INSUFFICIENT_RESOURCES;
+    Status = RETURN_OUT_OF_RESOURCES;
+    goto Done;
+  }
+  // It is a signature across the variable data and the Monotonic Count value.
+  CopyMem(&Backup, (UINT8 *)Image + ImageOffset, sizeof(Backup));
+  CopyMem((UINT8 *)Image + ImageOffset, &MonotonicCount, sizeof(MonotonicCount));
+  CryptoStatus = Sha256Update (HashContext, (UINT8 *)Image + ImageOffset, ImageSize - ImageOffset);
+  CopyMem((UINT8 *)Image + ImageOffset, &Backup, sizeof(Backup));
+  if (!CryptoStatus) {
+    DEBUG ((DEBUG_ERROR, "FmpAuthenticatedHandlerRsa2048Sha256: Sha256Update() failed\n"));
+    *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INSUFFICIENT_RESOURCES;
+    Status = RETURN_OUT_OF_RESOURCES;
+    goto Done;
+  }
+  CryptoStatus  = Sha256Final (HashContext, Digest);
+  if (!CryptoStatus) {
+    DEBUG ((DEBUG_ERROR, "FmpAuthenticatedHandlerRsa2048Sha256: Sha256Final() failed\n"));
+    *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INSUFFICIENT_RESOURCES;
+    Status = RETURN_OUT_OF_RESOURCES;
+    goto Done;
+  }
+
+  //
+  // Verify the RSA 2048 SHA 256 signature.
+  //
+  CryptoStatus = RsaPkcs1Verify (
+                   Rsa,
+                   Digest,
+                   SHA256_DIGEST_SIZE,
+                   CertBlockRsa2048Sha256->Signature,
+                   sizeof (CertBlockRsa2048Sha256->Signature)
+                   );
+  if (!CryptoStatus) {
+    //
+    // If RSA 2048 SHA 256 signature verification fails, AUTH tested failed bit is set.
+    //
+    DEBUG ((DEBUG_ERROR, "FmpAuthenticatedHandlerRsa2048Sha256: RsaPkcs1Verify() failed\n"));
+    *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_AUTH_ERROR;
+    Status = RETURN_SECURITY_VIOLATION;
+    goto Done;
+  }
+  DEBUG ((DEBUG_INFO, "FmpAuthenticatedHandlerRsa2048Sha256: PASS verification\n"));
+
+  *LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;
+  Status = RETURN_SUCCESS;
+
+Done:
+  //
+  // Free allocated resources used to perform RSA 2048 SHA 256 signature verification
+  //
+  if (Rsa != NULL) {
+    RsaFree (Rsa);
+  }
+  if (HashContext != NULL) {
+    FreePool (HashContext);
+  }
+
+  return Status;
+}
+
+/**
+  The constructor function to register FMP authentication handler.
+
+  @retval RETURN_SUCCESS   The constructor successfully .
+**/
+RETURN_STATUS
+EFIAPI
+FmpAuthenticationRsa2048Sha256LibConstructor(
+  VOID
+  )
+{
+  RETURN_STATUS  Status;
+
+  mPublicKey = (UINT8 *)PcdGetPtr(PcdRsa2048Sha256PublicKeyBuffer);
+  ASSERT(mPublicKey != NULL);
+  mPublicKeyBufferSize = PcdGetSize(PcdRsa2048Sha256PublicKeyBuffer);
+  ASSERT((mPublicKeyBufferSize % SHA256_DIGEST_SIZE) == 0);
+  mPublicKey = AllocateCopyPool(mPublicKeyBufferSize, mPublicKey);
+  ASSERT(mPublicKey != NULL);
+
+  Status = RegisterFmpAuthenticationHandler(&gEfiCertTypeRsa2048Sha256Guid, FmpAuthenticatedHandlerRsa2048Sha256);
+  ASSERT_EFI_ERROR(Status);
+
+  return RETURN_SUCCESS;
+}
diff --git a/SecurityPkg/Library/FmpAuthenticationRsa2048Sha256Lib/FmpAuthenticationRsa2048Sha256Lib.inf b/SecurityPkg/Library/FmpAuthenticationRsa2048Sha256Lib/FmpAuthenticationRsa2048Sha256Lib.inf
new file mode 100644
index 0000000..acae202
--- /dev/null
+++ b/SecurityPkg/Library/FmpAuthenticationRsa2048Sha256Lib/FmpAuthenticationRsa2048Sha256Lib.inf
@@ -0,0 +1,53 @@
+## @file
+#  FMP Authentication RSA2048SHA256 handler.
+#
+#  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = FmpAuthenticationRsa2048Sha256Lib
+  MODULE_UNI_FILE                = FmpAuthenticationRsa2048Sha256Lib.uni
+  FILE_GUID                      = 105FF0EA-A0C0-48A8-B8F7-E8B4D62A1019
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = NULL
+  CONSTRUCTOR                    = FmpAuthenticationRsa2048Sha256LibConstructor
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64 IPF EBC
+#
+
+[Sources]
+  FmpAuthenticationRsa2048Sha256Lib.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  SecurityPkg/SecurityPkg.dec
+  CryptoPkg/CryptoPkg.dec
+
+[LibraryClasses]
+  BaseLib
+  BaseMemoryLib
+  DebugLib
+  MemoryAllocationLib
+  BaseCryptLib
+  FmpAuthenticationLib
+
+[Pcd]
+  gEfiSecurityPkgTokenSpaceGuid.PcdRsa2048Sha256PublicKeyBuffer
+
+[Guids]
+  gEfiCertTypeRsa2048Sha256Guid
+  gEfiHashAlgorithmSha256Guid
diff --git a/SecurityPkg/Library/FmpAuthenticationRsa2048Sha256Lib/FmpAuthenticationRsa2048Sha256Lib.uni b/SecurityPkg/Library/FmpAuthenticationRsa2048Sha256Lib/FmpAuthenticationRsa2048Sha256Lib.uni
new file mode 100644
index 0000000..902edef
--- /dev/null
+++ b/SecurityPkg/Library/FmpAuthenticationRsa2048Sha256Lib/FmpAuthenticationRsa2048Sha256Lib.uni
@@ -0,0 +1,26 @@
+// /** @file
+// FMP Authentication RSA2048SHA256 handler.
+//
+// This library provide FMP Authentication RSA2048SHA256 handler to verify EFI_FIRMWARE_IMAGE_AUTHENTICATION.
+//
+// Caution: This module requires additional review when modified.
+// This library will have external input - capsule image.
+// This external input must be validated carefully to avoid security issues such as
+// buffer overflow or integer overflow.
+//
+// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+//
+// This program and the accompanying materials
+// are licensed and made available under the terms and conditions of the BSD License
+// which accompanies this distribution. The full text of the license may be found at
+// http://opensource.org/licenses/bsd-license.php
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT             #language en-US "FMP Authentication RSA2048SHA256 handler."
+
+#string STR_MODULE_DESCRIPTION          #language en-US "This library provide FMP Authentication RSA2048SHA256 handler to verify EFI_FIRMWARE_IMAGE_AUTHENTICATION."
+
-- 
2.7.4.windows.1



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

* [PATCH 23/45] SecurityPkg/SecurityPkg.dsc: Add FmpAuthentication*Lib.
  2016-09-21  6:44 [PATCH 00/45] Add capsule update and recovery sample Jiewen Yao
                   ` (21 preceding siblings ...)
  2016-09-21  6:45 ` [PATCH 22/45] SecurityPkg/FmpAuthenticationRsa2048Sha256Lib: Add " Jiewen Yao
@ 2016-09-21  6:45 ` Jiewen Yao
  2016-09-28  4:56   ` Zhang, Chao B
  2016-09-21  6:45 ` [PATCH 24/45] UefiCpuPkg/Include: Add Microcode FMP definition Jiewen Yao
                   ` (25 subsequent siblings)
  48 siblings, 1 reply; 83+ messages in thread
From: Jiewen Yao @ 2016-09-21  6:45 UTC (permalink / raw)
  To: edk2-devel; +Cc: Feng Tian, Star Zeng, Michael D Kinney, Liming Gao, Chao Zhang

Add FmpAuthentication*Lib to check build.

Cc: Feng Tian <feng.tian@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Chao Zhang <chao.b.zhang@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
---
 SecurityPkg/SecurityPkg.dsc | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/SecurityPkg/SecurityPkg.dsc b/SecurityPkg/SecurityPkg.dsc
index 3b36d0f..09d083e 100644
--- a/SecurityPkg/SecurityPkg.dsc
+++ b/SecurityPkg/SecurityPkg.dsc
@@ -211,6 +211,9 @@
   SecurityPkg/Library/DxeRsa2048Sha256GuidedSectionExtractLib/DxeRsa2048Sha256GuidedSectionExtractLib.inf
   SecurityPkg/Library/PeiRsa2048Sha256GuidedSectionExtractLib/PeiRsa2048Sha256GuidedSectionExtractLib.inf
 
+  SecurityPkg/Library/FmpAuthenticationPkcs7Lib/FmpAuthenticationPkcs7Lib.inf
+  SecurityPkg/Library/FmpAuthenticationRsa2048Sha256Lib/FmpAuthenticationRsa2048Sha256Lib.inf
+
   SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf
 
 [Components.IA32, Components.X64, Components.IPF]
-- 
2.7.4.windows.1



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

* [PATCH 24/45] UefiCpuPkg/Include: Add Microcode FMP definition.
  2016-09-21  6:44 [PATCH 00/45] Add capsule update and recovery sample Jiewen Yao
                   ` (22 preceding siblings ...)
  2016-09-21  6:45 ` [PATCH 23/45] SecurityPkg/SecurityPkg.dsc: Add FmpAuthentication*Lib Jiewen Yao
@ 2016-09-21  6:45 ` Jiewen Yao
  2016-09-21  6:45 ` [PATCH 25/45] UefiCpuPkg/Include: Add MicrocodeFlashAccessLib header Jiewen Yao
                   ` (24 subsequent siblings)
  48 siblings, 0 replies; 83+ messages in thread
From: Jiewen Yao @ 2016-09-21  6:45 UTC (permalink / raw)
  To: edk2-devel
  Cc: Jeff Fan, Feng Tian, Star Zeng, Michael D Kinney, Liming Gao,
	Chao Zhang

It defined ImageTypeId for Microcode.

Cc: Jeff Fan <jeff.fan@intel.com>
Cc: Feng Tian <feng.tian@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Chao Zhang <chao.b.zhang@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
---
 UefiCpuPkg/Include/Guid/MicrocodeFmp.h | 21 ++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/UefiCpuPkg/Include/Guid/MicrocodeFmp.h b/UefiCpuPkg/Include/Guid/MicrocodeFmp.h
new file mode 100644
index 0000000..88a1953
--- /dev/null
+++ b/UefiCpuPkg/Include/Guid/MicrocodeFmp.h
@@ -0,0 +1,21 @@
+/** @file
+
+  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __MICROCODE_FMP_GUID_H__
+#define __MICROCODE_FMP_GUID_H__
+
+#define MICROCODE_FMP_IMAGE_TYPE_ID_GUID { 0x96d4fdcd, 0x1502, 0x424d, { 0x9d, 0x4c, 0x9b, 0x12, 0xd2, 0xdc, 0xae, 0x5c } }
+
+extern EFI_GUID gMicrocodeFmpImageTypeIdGuid;
+
+#endif
-- 
2.7.4.windows.1



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

* [PATCH 25/45] UefiCpuPkg/Include: Add MicrocodeFlashAccessLib header.
  2016-09-21  6:44 [PATCH 00/45] Add capsule update and recovery sample Jiewen Yao
                   ` (23 preceding siblings ...)
  2016-09-21  6:45 ` [PATCH 24/45] UefiCpuPkg/Include: Add Microcode FMP definition Jiewen Yao
@ 2016-09-21  6:45 ` Jiewen Yao
  2016-09-21  6:45 ` [PATCH 26/45] UefiCpuPkg/UefiCpuPkg.dec: Add Microcode capsule related definition Jiewen Yao
                   ` (23 subsequent siblings)
  48 siblings, 0 replies; 83+ messages in thread
From: Jiewen Yao @ 2016-09-21  6:45 UTC (permalink / raw)
  To: edk2-devel
  Cc: Jeff Fan, Feng Tian, Star Zeng, Michael D Kinney, Liming Gao,
	Chao Zhang

This library is used to abstract microcode flash region access.
This library is consumed by a microcode capsule update module.

Cc: Jeff Fan <jeff.fan@intel.com>
Cc: Feng Tian <feng.tian@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Chao Zhang <chao.b.zhang@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
---
 UefiCpuPkg/Include/Library/MicrocodeFlashAccessLib.h | 39 ++++++++++++++++++++
 1 file changed, 39 insertions(+)

diff --git a/UefiCpuPkg/Include/Library/MicrocodeFlashAccessLib.h b/UefiCpuPkg/Include/Library/MicrocodeFlashAccessLib.h
new file mode 100644
index 0000000..fe2f630
--- /dev/null
+++ b/UefiCpuPkg/Include/Library/MicrocodeFlashAccessLib.h
@@ -0,0 +1,39 @@
+/** @file
+  Microcode flash device access library.
+
+  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+
+#ifndef __MICROCODE_FLASH_ACCESS_LIB_H__
+#define __MICROCODE_FLASH_ACCESS_LIB_H__
+
+/**
+  Perform microcode write opreation.
+
+  @param FlashAddress      The address of flash device to be accessed.
+  @param Buffer            The pointer to the data buffer.
+  @param Length            The length of data buffer in bytes.
+
+  @retval EFI_SUCCESS           The operation returns successfully.
+  @retval EFI_WRITE_PROTECTED   The flash device is read only.
+  @retval EFI_UNSUPPORTED       The flash device access is unsupported.
+  @retval EFI_INVALID_PARAMETER The input parameter is not valid.
+**/
+EFI_STATUS
+EFIAPI
+MicrocodeFlashWrite (
+  IN EFI_PHYSICAL_ADDRESS         FlashAddress,
+  IN VOID                         *Buffer,
+  IN UINTN                        Length
+  );
+
+#endif
-- 
2.7.4.windows.1



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

* [PATCH 26/45] UefiCpuPkg/UefiCpuPkg.dec: Add Microcode capsule related definition.
  2016-09-21  6:44 [PATCH 00/45] Add capsule update and recovery sample Jiewen Yao
                   ` (24 preceding siblings ...)
  2016-09-21  6:45 ` [PATCH 25/45] UefiCpuPkg/Include: Add MicrocodeFlashAccessLib header Jiewen Yao
@ 2016-09-21  6:45 ` Jiewen Yao
  2016-09-21  6:45 ` [PATCH 27/45] UefiCpuPkg/MicrocodeUpdate: Add MicrocodeUpdate component Jiewen Yao
                   ` (22 subsequent siblings)
  48 siblings, 0 replies; 83+ messages in thread
From: Jiewen Yao @ 2016-09-21  6:45 UTC (permalink / raw)
  To: edk2-devel
  Cc: Jeff Fan, Feng Tian, Star Zeng, Michael D Kinney, Liming Gao,
	Chao Zhang

1) Add Microcode capsule related GUID.
   gMicrocodeFmpImageTypeIdGuid
2) Add Microcode capsule related library.
   MicrocodeFlashAccessLib

Cc: Jeff Fan <jeff.fan@intel.com>
Cc: Feng Tian <feng.tian@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Chao Zhang <chao.b.zhang@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
---
 UefiCpuPkg/UefiCpuPkg.dec | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/UefiCpuPkg/UefiCpuPkg.dec b/UefiCpuPkg/UefiCpuPkg.dec
index 8674533..542704b 100644
--- a/UefiCpuPkg/UefiCpuPkg.dec
+++ b/UefiCpuPkg/UefiCpuPkg.dec
@@ -54,9 +54,16 @@
   ##
   MpInitLib|Include/Library/MpInitLib.h
 
+  ## @libraryclass  Provides services to access Microcode region on flash device.
+  #
+  MicrocodeFlashAccessLib|Include/Library/MicrocodeFlashAccessLib.h
+
 [Guids]
   gUefiCpuPkgTokenSpaceGuid      = { 0xac05bf33, 0x995a, 0x4ed4, { 0xaa, 0xb8, 0xef, 0x7a, 0xe8, 0xf, 0x5c, 0xb0 }}
 
+  ## Include/Guid/MicrocodeFmp.h
+  gMicrocodeFmpImageTypeIdGuid      = { 0x96d4fdcd, 0x1502, 0x424d, { 0x9d, 0x4c, 0x9b, 0x12, 0xd2, 0xdc, 0xae, 0x5c } }
+
 [Protocols]
   ## Include/Protocol/SmmCpuService.h
   gEfiSmmCpuServiceProtocolGuid  = { 0x1d202cab, 0xc8ab, 0x4d5c, { 0x94, 0xf7, 0x3c, 0xfc, 0xc0, 0xd3, 0xd3, 0x35 }}
-- 
2.7.4.windows.1



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

* [PATCH 27/45] UefiCpuPkg/MicrocodeUpdate: Add MicrocodeUpdate component.
  2016-09-21  6:44 [PATCH 00/45] Add capsule update and recovery sample Jiewen Yao
                   ` (25 preceding siblings ...)
  2016-09-21  6:45 ` [PATCH 26/45] UefiCpuPkg/UefiCpuPkg.dec: Add Microcode capsule related definition Jiewen Yao
@ 2016-09-21  6:45 ` Jiewen Yao
  2016-09-27  8:41   ` Fan, Jeff
  2016-09-21  6:45 ` [PATCH 28/45] UefiCpuPkg/MicrocodeFlashAccessLib: Add NULL MicrocodeFlashAccessLib Jiewen Yao
                   ` (21 subsequent siblings)
  48 siblings, 1 reply; 83+ messages in thread
From: Jiewen Yao @ 2016-09-21  6:45 UTC (permalink / raw)
  To: edk2-devel
  Cc: Jeff Fan, Feng Tian, Star Zeng, Michael D Kinney, Liming Gao,
	Chao Zhang

MicrocodeUpdate supports update Microcode region via UEFI FMP capsule.

MicrocodeUpdate SetImage() will perform the Microcode version,
ProcessorSignature/ProcessorFlag, and try to load microcode.
If and only if the Microcode is loaded successfully, and new Microcode
will be updated to system flash region.

Cc: Jeff Fan <jeff.fan@intel.com>
Cc: Feng Tian <feng.tian@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Chao Zhang <chao.b.zhang@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
---
 UefiCpuPkg/MicrocodeUpdate/MicrocodeFmp.c              | 641 ++++++++++++++++
 UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.c           | 775 ++++++++++++++++++++
 UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.h           | 299 ++++++++
 UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.inf         |  68 ++
 UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdateDxe.uni      |  21 +
 UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdateDxeExtra.uni |  20 +
 6 files changed, 1824 insertions(+)

diff --git a/UefiCpuPkg/MicrocodeUpdate/MicrocodeFmp.c b/UefiCpuPkg/MicrocodeUpdate/MicrocodeFmp.c
new file mode 100644
index 0000000..ee94b41
--- /dev/null
+++ b/UefiCpuPkg/MicrocodeUpdate/MicrocodeFmp.c
@@ -0,0 +1,641 @@
+/** @file
+  Produce FMP instance for Microcode.
+
+  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "MicrocodeUpdate.h"
+
+#define MICROCODE_FMP_PRIVATE_DATA_SIGNATURE  SIGNATURE_32('M', 'C', 'U', 'F')
+
+//
+// Microcode FMP private data structure.
+//
+
+typedef struct {
+  UINT32 LastAttemptVersion;
+  UINT32 LastAttemptStatus;
+} MICROCODE_FMP_LAST_ATTEMPT_VARIABLE;
+
+struct _MICROCODE_FMP_PRIVATE_DATA {
+  UINT32                               Signature;
+  EFI_FIRMWARE_MANAGEMENT_PROTOCOL     Fmp;
+  EFI_HANDLE                           Handle;
+  UINT8                                DescriptorCount;
+  EFI_FIRMWARE_IMAGE_DESCRIPTOR        *ImageDescriptor;
+  UINT32                               PackageVersion;
+  CHAR16                               *PackageVersionName;
+  MICROCODE_FMP_LAST_ATTEMPT_VARIABLE  LastAttempt;
+};
+
+typedef struct _MICROCODE_FMP_PRIVATE_DATA  MICROCODE_FMP_PRIVATE_DATA;
+
+#define MICROCODE_FMP_LAST_ATTEMPT_VARIABLE_NAME  L"MicrocodeLastAttempVar"
+
+/**
+  Returns a pointer to the MICROCODE_FMP_PRIVATE_DATA structure from the input a as Fmp.
+
+  If the signatures matches, then a pointer to the data structure that contains
+  a specified field of that data structure is returned.
+
+  @param  a              Pointer to the field specified by ServiceBinding within
+                         a data structure of type MICROCODE_FMP_PRIVATE_DATA.
+
+**/
+#define MICROCODE_FMP_PRIVATE_DATA_FROM_FMP(a) \
+  CR ( \
+  (a), \
+  MICROCODE_FMP_PRIVATE_DATA, \
+  Fmp, \
+  MICROCODE_FMP_PRIVATE_DATA_SIGNATURE \
+  )
+
+//
+// MicrocodeFmp driver private data
+//
+MICROCODE_FMP_PRIVATE_DATA *mMicrocodeFmpPrivate = NULL;
+
+EFI_FIRMWARE_MANAGEMENT_PROTOCOL mFirmwareManagementProtocol = {
+  FmpGetImageInfo,
+  FmpGetImage,
+  FmpSetImage,
+  FmpCheckImage,
+  FmpGetPackageInfo,
+  FmpSetPackageInfo
+};
+
+/**
+  Get current Microcode information.
+
+  @param[out]  ImageDescriptor  Microcode ImageDescriptor
+  @param[in]   DescriptorCount  The count of Microcode ImageDescriptor allocated.
+
+  @return Microcode count
+**/
+UINTN
+GetMicrocodeInfo(
+  OUT EFI_FIRMWARE_IMAGE_DESCRIPTOR  *ImageDescriptor, OPTIONAL
+  IN  UINTN                          DescriptorCount   OPTIONAL
+  );
+
+/**
+  Read Microcode.
+
+  @param  ImageIndex The index of Microcode image.
+  @param  Image      The Microcode image buffer.
+  @param  ImageSize  The size of Microcode image buffer in bytes.
+
+  @retval EFI_SUCCESS    The Microcode image is read.
+  @retval EFI_NOT_FOUND  The Microcode image is not found.
+**/
+EFI_STATUS
+MicrocodeRead(
+  IN UINTN      ImageIndex,
+  IN OUT VOID   *Image,
+  IN OUT UINTN  *ImageSize
+  );
+
+/**
+  Write Microcode.
+
+  @param  ImageIndex         The index of Microcode image.
+  @param  Image              The Microcode image buffer.
+  @param  ImageSize          The size of Microcode image buffer in bytes.
+  @param  LastAttemptVersion The last attempt version, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+  @param  LastAttemptStatus  The last attempt status, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+  @param  AbortReason        A pointer to a pointer to a null-terminated string providing more
+                             details for the aborted operation. The buffer is allocated by this function
+                             with AllocatePool(), and it is the caller's responsibility to free it with a
+                             call to FreePool().
+
+  @retval EFI_SUCCESS               The Microcode image is written.
+  @retval EFI_VOLUME_CORRUPTED      The Microcode image is corrupt.
+  @retval EFI_INCOMPATIBLE_VERSION  The Microcode image version is incorrect.
+  @retval EFI_SECURITY_VIOLATION    The Microcode image fails to load.
+  @retval EFI_WRITE_PROTECTED   The flash device is read only.
+**/
+EFI_STATUS
+MicrocodeWrite(
+  IN UINTN   ImageIndex,
+  IN VOID    *Image,
+  IN UINTN   ImageSize,
+  OUT UINT32 *LastAttemptVersion,
+  OUT UINT32 *LastAttemptStatus,
+  OUT CHAR16 **AbortReason
+  );
+
+/**
+  Initialize Microcode Descriptor.
+
+  @param MicrocodeFmpPrivate private data structure to be initialized.
+
+  @return EFI_SUCCESS Microcode Descriptor is initialized.
+**/
+EFI_STATUS
+InitializeMicrocodeDescriptor(
+  IN MICROCODE_FMP_PRIVATE_DATA *MicrocodeFmpPrivate
+  );
+
+/**
+  Returns information about the current firmware image(s) of the device.
+
+  This function allows a copy of the current firmware image to be created and saved.
+  The saved copy could later been used, for example, in firmware image recovery or rollback.
+
+  @param[in]      This               A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
+  @param[in, out] ImageInfoSize      A pointer to the size, in bytes, of the ImageInfo buffer.
+                                     On input, this is the size of the buffer allocated by the caller.
+                                     On output, it is the size of the buffer returned by the firmware
+                                     if the buffer was large enough, or the size of the buffer needed
+                                     to contain the image(s) information if the buffer was too small.
+  @param[in, out] ImageInfo          A pointer to the buffer in which firmware places the current image(s)
+                                     information. The information is an array of EFI_FIRMWARE_IMAGE_DESCRIPTORs.
+  @param[out]     DescriptorVersion  A pointer to the location in which firmware returns the version number
+                                     associated with the EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+  @param[out]     DescriptorCount    A pointer to the location in which firmware returns the number of
+                                     descriptors or firmware images within this device.
+  @param[out]     DescriptorSize     A pointer to the location in which firmware returns the size, in bytes,
+                                     of an individual EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+  @param[out]     PackageVersion     A version number that represents all the firmware images in the device.
+                                     The format is vendor specific and new version must have a greater value
+                                     than the old version. If PackageVersion is not supported, the value is
+                                     0xFFFFFFFF. A value of 0xFFFFFFFE indicates that package version comparison
+                                     is to be performed using PackageVersionName. A value of 0xFFFFFFFD indicates
+                                     that package version update is in progress.
+  @param[out]     PackageVersionName A pointer to a pointer to a null-terminated string representing the
+                                     package version name. The buffer is allocated by this function with
+                                     AllocatePool(), and it is the caller's responsibility to free it with a call
+                                     to FreePool().
+
+  @retval EFI_SUCCESS                The device was successfully updated with the new image.
+  @retval EFI_BUFFER_TOO_SMALL       The ImageInfo buffer was too small. The current buffer size
+                                     needed to hold the image(s) information is returned in ImageInfoSize.
+  @retval EFI_INVALID_PARAMETER      ImageInfoSize is NULL.
+  @retval EFI_DEVICE_ERROR           Valid information could not be returned. Possible corrupted image.
+
+**/
+EFI_STATUS
+EFIAPI
+FmpGetImageInfo (
+  IN        EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This,
+  IN OUT    UINTN                            *ImageInfoSize,
+  IN OUT    EFI_FIRMWARE_IMAGE_DESCRIPTOR    *ImageInfo,
+  OUT       UINT32                           *DescriptorVersion,
+  OUT       UINT8                            *DescriptorCount,
+  OUT       UINTN                            *DescriptorSize,
+  OUT       UINT32                           *PackageVersion,
+  OUT       CHAR16                           **PackageVersionName
+  )
+{
+  MICROCODE_FMP_PRIVATE_DATA *MicrocodeFmpPrivate;
+  UINTN                      Index;
+
+  MicrocodeFmpPrivate = MICROCODE_FMP_PRIVATE_DATA_FROM_FMP(This);
+
+  if(ImageInfoSize == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (*ImageInfoSize < sizeof(EFI_FIRMWARE_IMAGE_DESCRIPTOR) * MicrocodeFmpPrivate->DescriptorCount) {
+    *ImageInfoSize = sizeof(EFI_FIRMWARE_IMAGE_DESCRIPTOR) * MicrocodeFmpPrivate->DescriptorCount;
+    return EFI_BUFFER_TOO_SMALL;
+  }
+
+  if (ImageInfo == NULL ||
+      DescriptorVersion == NULL ||
+      DescriptorCount == NULL ||
+      DescriptorSize == NULL ||
+      PackageVersion == NULL ||
+      PackageVersionName == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  *ImageInfoSize      = sizeof(EFI_FIRMWARE_IMAGE_DESCRIPTOR) * MicrocodeFmpPrivate->DescriptorCount;
+  *DescriptorSize     = sizeof(EFI_FIRMWARE_IMAGE_DESCRIPTOR);
+  *DescriptorCount    = MicrocodeFmpPrivate->DescriptorCount;
+  *DescriptorVersion  = EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION;
+
+  //
+  // supports 1 ImageInfo descriptor
+  //
+  CopyMem(&ImageInfo[0], MicrocodeFmpPrivate->ImageDescriptor, sizeof(EFI_FIRMWARE_IMAGE_DESCRIPTOR) * MicrocodeFmpPrivate->DescriptorCount);
+  for (Index = 0; Index < MicrocodeFmpPrivate->DescriptorCount; Index++) {
+    if ((ImageInfo[Index].AttributesSetting & IMAGE_ATTRIBUTE_IN_USE) != 0) {
+      ImageInfo[Index].LastAttemptVersion = MicrocodeFmpPrivate->LastAttempt.LastAttemptVersion;
+      ImageInfo[Index].LastAttemptStatus = MicrocodeFmpPrivate->LastAttempt.LastAttemptStatus;
+    }
+  }
+
+  //
+  // package version
+  //
+  *PackageVersion = MicrocodeFmpPrivate->PackageVersion;
+  if (MicrocodeFmpPrivate->PackageVersionName != NULL) {
+    *PackageVersionName = AllocateCopyPool(StrSize(MicrocodeFmpPrivate->PackageVersionName), MicrocodeFmpPrivate->PackageVersionName);
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Retrieves a copy of the current firmware image of the device.
+
+  This function allows a copy of the current firmware image to be created and saved.
+  The saved copy could later been used, for example, in firmware image recovery or rollback.
+
+  @param[in]     This            A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
+  @param[in]     ImageIndex      A unique number identifying the firmware image(s) within the device.
+                                 The number is between 1 and DescriptorCount.
+  @param[in,out] Image           Points to the buffer where the current image is copied to.
+  @param[in,out] ImageSize       On entry, points to the size of the buffer pointed to by Image, in bytes.
+                                 On return, points to the length of the image, in bytes.
+
+  @retval EFI_SUCCESS            The device was successfully updated with the new image.
+  @retval EFI_BUFFER_TOO_SMALL   The buffer specified by ImageSize is too small to hold the
+                                 image. The current buffer size needed to hold the image is returned
+                                 in ImageSize.
+  @retval EFI_INVALID_PARAMETER  The Image was NULL.
+  @retval EFI_NOT_FOUND          The current image is not copied to the buffer.
+  @retval EFI_UNSUPPORTED        The operation is not supported.
+  @retval EFI_SECURITY_VIOLATIO  The operation could not be performed due to an authentication failure.
+
+**/
+EFI_STATUS
+EFIAPI
+FmpGetImage(
+  IN  EFI_FIRMWARE_MANAGEMENT_PROTOCOL  *This,
+  IN  UINT8                             ImageIndex,
+  IN  OUT  VOID                         *Image,
+  IN  OUT  UINTN                        *ImageSize
+  )
+{
+  MICROCODE_FMP_PRIVATE_DATA *MicrocodeFmpPrivate;
+  EFI_STATUS                 Status;
+
+  if (Image == NULL || ImageSize == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  MicrocodeFmpPrivate = MICROCODE_FMP_PRIVATE_DATA_FROM_FMP(This);
+
+  if (ImageIndex == 0 || ImageIndex > MicrocodeFmpPrivate->DescriptorCount || ImageSize == NULL || Image == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Status = MicrocodeRead(ImageIndex, (VOID *)Image, ImageSize);
+  return Status;
+}
+
+/**
+  Updates the firmware image of the device.
+
+  This function updates the hardware with the new firmware image.
+  This function returns EFI_UNSUPPORTED if the firmware image is not updatable.
+  If the firmware image is updatable, the function should perform the following minimal validations
+  before proceeding to do the firmware image update.
+  - Validate the image authentication if image has attribute
+    IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED. The function returns
+    EFI_SECURITY_VIOLATION if the validation fails.
+  - Validate the image is a supported image for this device. The function returns EFI_ABORTED if
+    the image is unsupported. The function can optionally provide more detailed information on
+    why the image is not a supported image.
+  - Validate the data from VendorCode if not null. Image validation must be performed before
+    VendorCode data validation. VendorCode data is ignored or considered invalid if image
+    validation failed. The function returns EFI_ABORTED if the data is invalid.
+
+  VendorCode enables vendor to implement vendor-specific firmware image update policy. Null if
+  the caller did not specify the policy or use the default policy. As an example, vendor can implement
+  a policy to allow an option to force a firmware image update when the abort reason is due to the new
+  firmware image version is older than the current firmware image version or bad image checksum.
+  Sensitive operations such as those wiping the entire firmware image and render the device to be
+  non-functional should be encoded in the image itself rather than passed with the VendorCode.
+  AbortReason enables vendor to have the option to provide a more detailed description of the abort
+  reason to the caller.
+
+  @param[in]  This               A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
+  @param[in]  ImageIndex         A unique number identifying the firmware image(s) within the device.
+                                 The number is between 1 and DescriptorCount.
+  @param[in]  Image              Points to the new image.
+  @param[in]  ImageSize          Size of the new image in bytes.
+  @param[in]  VendorCode         This enables vendor to implement vendor-specific firmware image update policy.
+                                 Null indicates the caller did not specify the policy or use the default policy.
+  @param[in]  Progress           A function used by the driver to report the progress of the firmware update.
+  @param[out] AbortReason        A pointer to a pointer to a null-terminated string providing more
+                                 details for the aborted operation. The buffer is allocated by this function
+                                 with AllocatePool(), and it is the caller's responsibility to free it with a
+                                 call to FreePool().
+
+  @retval EFI_SUCCESS            The device was successfully updated with the new image.
+  @retval EFI_ABORTED            The operation is aborted.
+  @retval EFI_INVALID_PARAMETER  The Image was NULL.
+  @retval EFI_UNSUPPORTED        The operation is not supported.
+  @retval EFI_SECURITY_VIOLATIO  The operation could not be performed due to an authentication failure.
+
+**/
+EFI_STATUS
+EFIAPI
+FmpSetImage(
+  IN  EFI_FIRMWARE_MANAGEMENT_PROTOCOL                 *This,
+  IN  UINT8                                            ImageIndex,
+  IN  CONST VOID                                       *Image,
+  IN  UINTN                                            ImageSize,
+  IN  CONST VOID                                       *VendorCode,
+  IN  EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS    Progress,
+  OUT CHAR16                                           **AbortReason
+  )
+{
+  EFI_STATUS                 Status;
+  EFI_STATUS                 VarStatus;
+  MICROCODE_FMP_PRIVATE_DATA *MicrocodeFmpPrivate;
+
+  if (Image == NULL || AbortReason == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  MicrocodeFmpPrivate = MICROCODE_FMP_PRIVATE_DATA_FROM_FMP(This);
+  *AbortReason     = NULL;
+
+  if (ImageIndex == 0 || ImageIndex > MicrocodeFmpPrivate->DescriptorCount || Image == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Status = MicrocodeWrite(ImageIndex, (VOID *)Image, ImageSize, &MicrocodeFmpPrivate->LastAttempt.LastAttemptVersion, &MicrocodeFmpPrivate->LastAttempt.LastAttemptStatus, AbortReason);
+  DEBUG((EFI_D_INFO, "SetImage - LastAttemp Version - 0x%x, State - 0x%x\n", MicrocodeFmpPrivate->LastAttempt.LastAttemptVersion, MicrocodeFmpPrivate->LastAttempt.LastAttemptStatus));
+  VarStatus = gRT->SetVariable(
+                     MICROCODE_FMP_LAST_ATTEMPT_VARIABLE_NAME,
+                     &gEfiCallerIdGuid,
+                     EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
+                     sizeof(MicrocodeFmpPrivate->LastAttempt),
+                     &MicrocodeFmpPrivate->LastAttempt
+                     );
+  DEBUG((EFI_D_INFO, "SetLastAttemp - %r\n", VarStatus));
+
+  if (!EFI_ERROR(Status)) {
+    InitializeMicrocodeDescriptor(MicrocodeFmpPrivate);
+  }
+
+  return Status;
+}
+
+/**
+  Checks if the firmware image is valid for the device.
+
+  This function allows firmware update application to validate the firmware image without
+  invoking the SetImage() first.
+
+  @param[in]  This               A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
+  @param[in]  ImageIndex         A unique number identifying the firmware image(s) within the device.
+                                 The number is between 1 and DescriptorCount.
+  @param[in]  Image              Points to the new image.
+  @param[in]  ImageSize          Size of the new image in bytes.
+  @param[out] ImageUpdatable     Indicates if the new image is valid for update. It also provides,
+                                 if available, additional information if the image is invalid.
+
+  @retval EFI_SUCCESS            The image was successfully checked.
+  @retval EFI_INVALID_PARAMETER  The Image was NULL.
+  @retval EFI_UNSUPPORTED        The operation is not supported.
+  @retval EFI_SECURITY_VIOLATIO  The operation could not be performed due to an authentication failure.
+
+**/
+EFI_STATUS
+EFIAPI
+FmpCheckImage(
+  IN  EFI_FIRMWARE_MANAGEMENT_PROTOCOL  *This,
+  IN  UINT8                             ImageIndex,
+  IN  CONST VOID                        *Image,
+  IN  UINTN                             ImageSize,
+  OUT UINT32                            *ImageUpdatable
+  )
+{
+  return EFI_UNSUPPORTED;
+}
+
+/**
+  Returns information about the firmware package.
+
+  This function returns package information.
+
+  @param[in]  This                     A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
+  @param[out] PackageVersion           A version number that represents all the firmware images in the device.
+                                       The format is vendor specific and new version must have a greater value
+                                       than the old version. If PackageVersion is not supported, the value is
+                                       0xFFFFFFFF. A value of 0xFFFFFFFE indicates that package version
+                                       comparison is to be performed using PackageVersionName. A value of
+                                       0xFFFFFFFD indicates that package version update is in progress.
+  @param[out] PackageVersionName       A pointer to a pointer to a null-terminated string representing
+                                       the package version name. The buffer is allocated by this function with
+                                       AllocatePool(), and it is the caller's responsibility to free it with a
+                                       call to FreePool().
+  @param[out] PackageVersionNameMaxLen The maximum length of package version name if device supports update of
+                                       package version name. A value of 0 indicates the device does not support
+                                       update of package version name. Length is the number of Unicode characters,
+                                       including the terminating null character.
+  @param[out] AttributesSupported      Package attributes that are supported by this device. See 'Package Attribute
+                                       Definitions' for possible returned values of this parameter. A value of 1
+                                       indicates the attribute is supported and the current setting value is
+                                       indicated in AttributesSetting. A value of 0 indicates the attribute is not
+                                       supported and the current setting value in AttributesSetting is meaningless.
+  @param[out] AttributesSetting        Package attributes. See 'Package Attribute Definitions' for possible returned
+                                       values of this parameter
+
+  @retval EFI_SUCCESS                  The package information was successfully returned.
+  @retval EFI_UNSUPPORTED              The operation is not supported.
+
+**/
+EFI_STATUS
+EFIAPI
+FmpGetPackageInfo(
+  IN  EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This,
+  OUT UINT32                           *PackageVersion,
+  OUT CHAR16                           **PackageVersionName,
+  OUT UINT32                           *PackageVersionNameMaxLen,
+  OUT UINT64                           *AttributesSupported,
+  OUT UINT64                           *AttributesSetting
+  )
+{
+  return EFI_UNSUPPORTED;
+}
+
+/**
+  Updates information about the firmware package.
+
+  This function updates package information.
+  This function returns EFI_UNSUPPORTED if the package information is not updatable.
+  VendorCode enables vendor to implement vendor-specific package information update policy.
+  Null if the caller did not specify this policy or use the default policy.
+
+  @param[in]  This               A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
+  @param[in]  Image              Points to the authentication image.
+                                 Null if authentication is not required.
+  @param[in]  ImageSize          Size of the authentication image in bytes.
+                                 0 if authentication is not required.
+  @param[in]  VendorCode         This enables vendor to implement vendor-specific firmware
+                                 image update policy.
+                                 Null indicates the caller did not specify this policy or use
+                                 the default policy.
+  @param[in]  PackageVersion     The new package version.
+  @param[in]  PackageVersionName A pointer to the new null-terminated Unicode string representing
+                                 the package version name.
+                                 The string length is equal to or less than the value returned in
+                                 PackageVersionNameMaxLen.
+
+  @retval EFI_SUCCESS            The device was successfully updated with the new package
+                                 information.
+  @retval EFI_INVALID_PARAMETER  The PackageVersionName length is longer than the value
+                                 returned in PackageVersionNameMaxLen.
+  @retval EFI_UNSUPPORTED        The operation is not supported.
+  @retval EFI_SECURITY_VIOLATIO  The operation could not be performed due to an authentication failure.
+
+**/
+EFI_STATUS
+EFIAPI
+FmpSetPackageInfo(
+  IN  EFI_FIRMWARE_MANAGEMENT_PROTOCOL   *This,
+  IN  CONST VOID                         *Image,
+  IN  UINTN                              ImageSize,
+  IN  CONST VOID                         *VendorCode,
+  IN  UINT32                             PackageVersion,
+  IN  CONST CHAR16                       *PackageVersionName
+  )
+{
+  return EFI_UNSUPPORTED;
+}
+
+/**
+  Initialize Microcode Descriptor.
+
+  @param MicrocodeFmpPrivate private data structure to be initialized.
+
+  @return EFI_SUCCESS Microcode Descriptor is initialized.
+**/
+EFI_STATUS
+InitializeMicrocodeDescriptor (
+  IN MICROCODE_FMP_PRIVATE_DATA *MicrocodeFmpPrivate
+  )
+{
+  UINT8  CurrentMicrocodeCount;
+
+  CurrentMicrocodeCount = (UINT8)GetMicrocodeInfo(NULL, 0);
+
+  if (CurrentMicrocodeCount > MicrocodeFmpPrivate->DescriptorCount) {
+    if (MicrocodeFmpPrivate->ImageDescriptor != NULL) {
+      FreePool(MicrocodeFmpPrivate->ImageDescriptor);
+      MicrocodeFmpPrivate->ImageDescriptor = NULL;
+    }
+  } else {
+    ZeroMem(MicrocodeFmpPrivate->ImageDescriptor, MicrocodeFmpPrivate->DescriptorCount * sizeof(EFI_FIRMWARE_IMAGE_DESCRIPTOR));
+  }
+
+  MicrocodeFmpPrivate->DescriptorCount = CurrentMicrocodeCount;
+
+  if (MicrocodeFmpPrivate->ImageDescriptor == NULL) {
+    MicrocodeFmpPrivate->ImageDescriptor = AllocateZeroPool(MicrocodeFmpPrivate->DescriptorCount * sizeof(EFI_FIRMWARE_IMAGE_DESCRIPTOR));
+    if (MicrocodeFmpPrivate->ImageDescriptor == NULL) {
+      return EFI_OUT_OF_RESOURCES;
+    }
+  }
+
+  CurrentMicrocodeCount = (UINT8)GetMicrocodeInfo(MicrocodeFmpPrivate->ImageDescriptor, MicrocodeFmpPrivate->DescriptorCount);
+  ASSERT(CurrentMicrocodeCount == MicrocodeFmpPrivate->DescriptorCount);
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Initialize MicrocodeFmpDriver private data structure.
+
+  @param MicrocodeFmpPrivate private data structure to be initialized.
+
+  @return EFI_SUCCESS private data is initialized.
+**/
+EFI_STATUS
+InitializePrivateData(
+  IN MICROCODE_FMP_PRIVATE_DATA *MicrocodeFmpPrivate
+  )
+{
+  EFI_STATUS       Status;
+  EFI_STATUS       VarStatus;
+  UINTN            VarSize;
+
+  MicrocodeFmpPrivate->Signature       = MICROCODE_FMP_PRIVATE_DATA_SIGNATURE;
+  MicrocodeFmpPrivate->Handle          = NULL;
+  CopyMem(&MicrocodeFmpPrivate->Fmp, &mFirmwareManagementProtocol, sizeof(EFI_FIRMWARE_MANAGEMENT_PROTOCOL));
+
+  MicrocodeFmpPrivate->PackageVersion = 0x1;
+  MicrocodeFmpPrivate->PackageVersionName = L"Microcode";
+
+  MicrocodeFmpPrivate->LastAttempt.LastAttemptVersion = 0x0;
+  MicrocodeFmpPrivate->LastAttempt.LastAttemptStatus = 0x0;
+  VarSize = sizeof(MicrocodeFmpPrivate->LastAttempt);
+  VarStatus = gRT->GetVariable(
+                     MICROCODE_FMP_LAST_ATTEMPT_VARIABLE_NAME,
+                     &gEfiCallerIdGuid,
+                     NULL,
+                     &VarSize,
+                     &MicrocodeFmpPrivate->LastAttempt
+                     );
+  DEBUG((EFI_D_INFO, "GetLastAttemp - %r\n", VarStatus));
+  DEBUG((EFI_D_INFO, "GetLastAttemp Version - 0x%x, State - 0x%x\n", MicrocodeFmpPrivate->LastAttempt.LastAttemptVersion, MicrocodeFmpPrivate->LastAttempt.LastAttemptStatus));
+
+  Status = InitializeMicrocodeDescriptor(MicrocodeFmpPrivate);
+
+  return Status;
+}
+
+/**
+  Microcode FMP module entrypoint
+
+  @param  ImageHandle       The firmware allocated handle for the EFI image.
+  @param  SystemTable       A pointer to the EFI System Table.
+
+  @return EFI_SUCCESS Microcode FMP module is initialized.
+**/
+EFI_STATUS
+EFIAPI
+MicrocodeFmpMain (
+  IN EFI_HANDLE                         ImageHandle,
+  IN EFI_SYSTEM_TABLE                   *SystemTable
+  )
+{
+  EFI_STATUS                            Status;
+
+  //
+  // Initialize MicrocodeFmpPrivateData
+  //
+  mMicrocodeFmpPrivate = AllocateZeroPool (sizeof(MICROCODE_FMP_PRIVATE_DATA));
+  if (mMicrocodeFmpPrivate == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  Status = InitializePrivateData(mMicrocodeFmpPrivate);
+  if (EFI_ERROR(Status)) {
+    FreePool(mMicrocodeFmpPrivate);
+    mMicrocodeFmpPrivate = NULL;
+    return Status;
+  }
+
+  //
+  // Install FMP protocol.
+  //
+  Status = gBS->InstallProtocolInterface (
+                  &mMicrocodeFmpPrivate->Handle,
+                  &gEfiFirmwareManagementProtocolGuid,
+                  EFI_NATIVE_INTERFACE,
+                  &mMicrocodeFmpPrivate->Fmp
+                  );
+  if (EFI_ERROR (Status)) {
+    FreePool(mMicrocodeFmpPrivate);
+    mMicrocodeFmpPrivate = NULL;
+    return Status;
+  }
+
+  return Status;
+}
diff --git a/UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.c b/UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.c
new file mode 100644
index 0000000..d19eca9
--- /dev/null
+++ b/UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.c
@@ -0,0 +1,775 @@
+/** @file
+  SetImage instance to update Microcode.
+
+  Caution: This module requires additional review when modified.
+  This module will have external input - capsule image.
+  This external input must be validated carefully to avoid security issue like
+  buffer overflow, integer overflow.
+
+  MicrocodeWrite() and VerifyMicrocode() will receive untrusted input and do basic validation.
+
+  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "MicrocodeUpdate.h"
+
+/**
+  Get Microcode Region.
+
+  @param[out] MicrocodePatchAddress      The address of Microcode
+  @param[out] MicrocodePatchRegionSize   The region size of Microcode
+
+  @retval TRUE   The Microcode region is returned.
+  @retval FALSE  No Microcode region.
+**/
+BOOLEAN
+GetMicrocodeRegion(
+  OUT UINT64   *MicrocodePatchAddress,
+  OUT UINT64   *MicrocodePatchRegionSize
+  )
+{
+  *MicrocodePatchAddress = PcdGet64(PcdCpuMicrocodePatchAddress);
+  *MicrocodePatchRegionSize = PcdGet64(PcdCpuMicrocodePatchRegionSize);
+
+  if ((*MicrocodePatchAddress == 0) || (*MicrocodePatchRegionSize == 0)) {
+    return FALSE;
+  }
+
+  return TRUE;
+}
+
+/**
+  Get Microcode update signature of currently loaded Microcode update.
+
+  @return  Microcode signature.
+
+**/
+UINT32
+GetCurrentMicrocodeSignature(
+  VOID
+  )
+{
+  UINT64 Signature;
+
+  AsmWriteMsr64(MSR_IA32_BIOS_SIGN_ID, 0);
+  AsmCpuid(CPUID_VERSION_INFO, NULL, NULL, NULL, NULL);
+  Signature = AsmReadMsr64(MSR_IA32_BIOS_SIGN_ID);
+  return (UINT32)RShiftU64(Signature, 32);
+}
+
+/**
+  Get current processor signature.
+
+  @return current processor signature.
+**/
+UINT32
+GetCurrentProcessorSignature(
+  VOID
+  )
+{
+  UINT32                                  RegEax;
+  AsmCpuid(CPUID_VERSION_INFO, &RegEax, NULL, NULL, NULL);
+  return RegEax;
+}
+
+/**
+  Get current platform ID.
+
+  @return current platform ID.
+**/
+UINT8
+GetCurrentPlatformId(
+  VOID
+  )
+{
+  UINT8                                   PlatformId;
+
+  PlatformId = (UINT8)AsmMsrBitFieldRead64(MSR_IA32_PLATFORM_ID, 50, 52);
+  return PlatformId;
+}
+
+/**
+  Load new Microcode.
+
+  @param Address  The address of new Microcode.
+
+  @return  Loaded Microcode signature.
+
+**/
+UINT32
+LoadMicrocode(
+  IN UINT64  Address
+  )
+{
+  AsmWriteMsr64(MSR_IA32_BIOS_UPDT_TRIG, Address);
+  return GetCurrentMicrocodeSignature();
+}
+
+/**
+  Get current Microcode information.
+
+  @param[out]  ImageDescriptor  Microcode ImageDescriptor
+  @param[in]   DescriptorCount  The count of Microcode ImageDescriptor allocated.
+
+  @return Microcode count
+**/
+UINTN
+GetMicrocodeInfo(
+  OUT EFI_FIRMWARE_IMAGE_DESCRIPTOR  *ImageDescriptor, OPTIONAL
+  IN  UINTN                          DescriptorCount   OPTIONAL
+  )
+{
+  BOOLEAN                                 Result;
+  UINT64                                  MicrocodePatchAddress;
+  UINT64                                  MicrocodePatchRegionSize;
+  CPU_MICROCODE_HEADER                    *MicrocodeEntryPoint;
+  UINTN                                   MicrocodeEnd;
+  UINTN                                   TotalSize;
+  UINTN                                   Count;
+  UINT64                                  ImageAttributes;
+  UINT32                                  CurrentRevision;
+
+  Result = GetMicrocodeRegion(&MicrocodePatchAddress, &MicrocodePatchRegionSize);
+  if (!Result) {
+    DEBUG((EFI_D_ERROR, "Fail to get Microcode Region\n"));
+    return 0;
+  }
+  DEBUG((EFI_D_ERROR, "Microcode Region - 0x%lx - 0x%lx\n", MicrocodePatchAddress, MicrocodePatchRegionSize));
+
+  Count = 0;
+  CurrentRevision = GetCurrentMicrocodeSignature();
+
+  MicrocodeEnd = (UINTN)(MicrocodePatchAddress + MicrocodePatchRegionSize);
+  MicrocodeEntryPoint = (CPU_MICROCODE_HEADER *) (UINTN) MicrocodePatchAddress;
+  do {
+    if (MicrocodeEntryPoint->HeaderVersion == 0x1 && MicrocodeEntryPoint->LoaderRevision == 0x1) {
+      //
+      // It is the microcode header. It is not the padding data between microcode patches
+      // becasue the padding data should not include 0x00000001 and it should be the repeated
+      // byte format (like 0xXYXYXYXY....).
+      //
+      if (MicrocodeEntryPoint->DataSize == 0) {
+        TotalSize = 2048;
+      } else {
+        TotalSize = MicrocodeEntryPoint->TotalSize;
+      }
+
+      if (ImageDescriptor != NULL && DescriptorCount > Count) {
+        ImageDescriptor[Count].ImageIndex = (UINT8)(Count + 1);
+        CopyGuid (&ImageDescriptor[Count].ImageTypeId, &gMicrocodeFmpImageTypeIdGuid);
+        ImageDescriptor[Count].ImageId = LShiftU64(MicrocodeEntryPoint->ProcessorFlags, 32) + MicrocodeEntryPoint->ProcessorSignature.Uint32;
+        ImageDescriptor[Count].ImageIdName = NULL;
+        ImageDescriptor[Count].Version = MicrocodeEntryPoint->UpdateRevision;
+        ImageDescriptor[Count].VersionName = NULL;
+        ImageDescriptor[Count].Size = TotalSize;
+        ImageAttributes = IMAGE_ATTRIBUTE_IMAGE_UPDATABLE | IMAGE_ATTRIBUTE_RESET_REQUIRED;
+        if (CurrentRevision == MicrocodeEntryPoint->UpdateRevision) {
+          ImageAttributes |= IMAGE_ATTRIBUTE_IN_USE;
+        }
+        ImageDescriptor[Count].AttributesSupported = ImageAttributes | IMAGE_ATTRIBUTE_IN_USE;
+        ImageDescriptor[Count].AttributesSetting = ImageAttributes;
+        ImageDescriptor[Count].Compatibilities = 0;
+        ImageDescriptor[Count].LowestSupportedImageVersion = MicrocodeEntryPoint->UpdateRevision; // do not support rollback
+        ImageDescriptor[Count].LastAttemptVersion = 0;
+        ImageDescriptor[Count].LastAttemptStatus = 0;
+        ImageDescriptor[Count].HardwareInstance = 0;
+      }
+    } else {
+      //
+      // It is the padding data between the microcode patches for microcode patches alignment.
+      // Because the microcode patch is the multiple of 1-KByte, the padding data should not
+      // exist if the microcode patch alignment value is not larger than 1-KByte. So, the microcode
+      // alignment value should be larger than 1-KByte. We could skip SIZE_1KB padding data to
+      // find the next possible microcode patch header.
+      //
+      MicrocodeEntryPoint = (CPU_MICROCODE_HEADER *) (((UINTN) MicrocodeEntryPoint) + SIZE_1KB);
+      continue;
+    }
+
+    Count++;
+    ASSERT(Count < 0xFF);
+
+    //
+    // Get the next patch.
+    //
+    MicrocodeEntryPoint = (CPU_MICROCODE_HEADER *) (((UINTN) MicrocodeEntryPoint) + TotalSize);
+  } while (((UINTN) MicrocodeEntryPoint < MicrocodeEnd));
+
+  return Count;
+}
+
+/**
+  Read Microcode.
+
+  @param  ImageIndex The index of Microcode image.
+  @param  Image      The Microcode image buffer.
+  @param  ImageSize  The size of Microcode image buffer in bytes.
+
+  @retval EFI_SUCCESS    The Microcode image is read.
+  @retval EFI_NOT_FOUND  The Microcode image is not found.
+**/
+EFI_STATUS
+MicrocodeRead(
+  IN UINTN      ImageIndex,
+  IN OUT VOID   *Image,
+  IN OUT UINTN  *ImageSize
+  )
+{
+  BOOLEAN                                 Result;
+  UINT64                                  MicrocodePatchAddress;
+  UINT64                                  MicrocodePatchRegionSize;
+  CPU_MICROCODE_HEADER                    *MicrocodeEntryPoint;
+  UINTN                                   MicrocodeEnd;
+  UINTN                                   TotalSize;
+  UINTN                                   Count;
+
+  Result = GetMicrocodeRegion(&MicrocodePatchAddress, &MicrocodePatchRegionSize);
+  if (!Result) {
+    DEBUG((EFI_D_ERROR, "Fail to get Microcode Region\n"));
+    return EFI_NOT_FOUND;
+  }
+  DEBUG((EFI_D_ERROR, "Microcode Region - 0x%lx - 0x%lx\n", MicrocodePatchAddress, MicrocodePatchRegionSize));
+
+  Count = 0;
+
+  MicrocodeEnd = (UINTN)(MicrocodePatchAddress + MicrocodePatchRegionSize);
+  MicrocodeEntryPoint = (CPU_MICROCODE_HEADER *)(UINTN)MicrocodePatchAddress;
+  do {
+    if (MicrocodeEntryPoint->HeaderVersion == 0x1 && MicrocodeEntryPoint->LoaderRevision == 0x1) {
+      //
+      // It is the microcode header. It is not the padding data between microcode patches
+      // becasue the padding data should not include 0x00000001 and it should be the repeated
+      // byte format (like 0xXYXYXYXY....).
+      //
+      if (MicrocodeEntryPoint->DataSize == 0) {
+        TotalSize = 2048;
+      } else {
+        TotalSize = MicrocodeEntryPoint->TotalSize;
+      }
+
+    } else {
+      //
+      // It is the padding data between the microcode patches for microcode patches alignment.
+      // Because the microcode patch is the multiple of 1-KByte, the padding data should not
+      // exist if the microcode patch alignment value is not larger than 1-KByte. So, the microcode
+      // alignment value should be larger than 1-KByte. We could skip SIZE_1KB padding data to
+      // find the next possible microcode patch header.
+      //
+      MicrocodeEntryPoint = (CPU_MICROCODE_HEADER *)(((UINTN)MicrocodeEntryPoint) + SIZE_1KB);
+      continue;
+    }
+
+    Count++;
+    ASSERT(Count < 0xFF);
+
+    //
+    // Get the next patch.
+    //
+    MicrocodeEntryPoint = (CPU_MICROCODE_HEADER *)(((UINTN)MicrocodeEntryPoint) + TotalSize);
+  } while (((UINTN)MicrocodeEntryPoint < MicrocodeEnd));
+
+  return EFI_NOT_FOUND;
+}
+
+/**
+  Verify Microcode.
+
+  @param  Image              The Microcode image buffer.
+  @param  ImageSize          The size of Microcode image buffer in bytes.
+  @param  TryLoad            Try to load Microcode or not.
+  @param  LastAttemptStatus  The last attempt status, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+  @param  AbortReason        A pointer to a pointer to a null-terminated string providing more
+                             details for the aborted operation. The buffer is allocated by this function
+                             with AllocatePool(), and it is the caller's responsibility to free it with a
+                             call to FreePool().
+
+  @retval EFI_SUCCESS               The Microcode image passes verification.
+  @retval EFI_VOLUME_CORRUPTED      The Microcode image is corrupt.
+  @retval EFI_INCOMPATIBLE_VERSION  The Microcode image version is incorrect.
+  @retval EFI_UNSUPPORTED           The Microcode ProcessorSignature or ProcessorFlags is incorrect.
+  @retval EFI_SECURITY_VIOLATION    The Microcode image fails to load.
+**/
+EFI_STATUS
+VerifyMicrocode(
+  IN VOID    *Image,
+  IN UINTN   ImageSize,
+  IN BOOLEAN TryLoad,
+  OUT UINT32 *LastAttemptStatus,
+  OUT CHAR16 **AbortReason
+  )
+{
+  UINTN                                   Index;
+  CPU_MICROCODE_HEADER                    *MicrocodeEntryPoint;
+  UINTN                                   TotalSize;
+  UINTN                                   DataSize;
+  UINT32                                  CurrentRevision;
+  UINT32                                  CurrentProcessorSignature;
+  UINT8                                   CurrentPlatformId;
+  UINT32                                  CheckSum32;
+  UINTN                                   ExtendedTableLength;
+  UINT32                                  ExtendedTableCount;
+  CPU_MICROCODE_EXTENDED_TABLE            *ExtendedTable;
+  CPU_MICROCODE_EXTENDED_TABLE_HEADER     *ExtendedTableHeader;
+  BOOLEAN                                 CorrectMicrocode;
+
+  //
+  // Check HeaderVersion
+  //
+  MicrocodeEntryPoint = Image;
+  if (MicrocodeEntryPoint->HeaderVersion != 0x1) {
+    DEBUG((EFI_D_ERROR, "VerifyMicrocode - fail on HeaderVersion\n"));
+    *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INVALID_FORMAT;
+    if (AbortReason != NULL) {
+      *AbortReason = AllocateCopyPool(sizeof(L"InvalidHeaderVersion"), L"InvalidHeaderVersion");
+    }
+    return EFI_INCOMPATIBLE_VERSION;
+  }
+  //
+  // Check LoaderRevision
+  //
+  if (MicrocodeEntryPoint->LoaderRevision != 0x1) {
+    DEBUG((EFI_D_ERROR, "VerifyMicrocode - fail on LoaderRevision\n"));
+    *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INVALID_FORMAT;
+    if (AbortReason != NULL) {
+      *AbortReason = AllocateCopyPool(sizeof(L"InvalidLoaderVersion"), L"InvalidLoaderVersion");
+    }
+    return EFI_INCOMPATIBLE_VERSION;
+  }
+  //
+  // Check Size
+  //
+  if (MicrocodeEntryPoint->DataSize == 0) {
+    TotalSize = 2048;
+  } else {
+    TotalSize = MicrocodeEntryPoint->TotalSize;
+  }
+  if (TotalSize <= sizeof(CPU_MICROCODE_HEADER)) {
+    DEBUG((EFI_D_ERROR, "VerifyMicrocode - TotalSize too small\n"));
+    *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INVALID_FORMAT;
+    if (AbortReason != NULL) {
+      *AbortReason = AllocateCopyPool(sizeof(L"InvalidTotalSize"), L"InvalidTotalSize");
+    }
+    return EFI_VOLUME_CORRUPTED;
+  }
+  if (TotalSize != ImageSize) {
+    DEBUG((EFI_D_ERROR, "VerifyMicrocode - fail on TotalSize\n"));
+    *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INVALID_FORMAT;
+    if (AbortReason != NULL) {
+      *AbortReason = AllocateCopyPool(sizeof(L"InvalidTotalSize"), L"InvalidTotalSize");
+    }
+    return EFI_VOLUME_CORRUPTED;
+  }
+  //
+  // Check CheckSum32
+  //
+  if (MicrocodeEntryPoint->DataSize == 0) {
+    DataSize = 2048 - sizeof(CPU_MICROCODE_HEADER);
+  } else {
+    DataSize = MicrocodeEntryPoint->DataSize;
+  }
+  if (DataSize > TotalSize - sizeof(CPU_MICROCODE_HEADER)) {
+    DEBUG((EFI_D_ERROR, "VerifyMicrocode - DataSize too big\n"));
+    *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INVALID_FORMAT;
+    if (AbortReason != NULL) {
+      *AbortReason = AllocateCopyPool(sizeof(L"InvalidDataSize"), L"InvalidDataSize");
+    }
+    return EFI_VOLUME_CORRUPTED;
+  }
+  if ((DataSize & 0x3) != 0) {
+    DEBUG((EFI_D_ERROR, "VerifyMicrocode - DataSize not aligned\n"));
+    *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INVALID_FORMAT;
+    if (AbortReason != NULL) {
+      *AbortReason = AllocateCopyPool(sizeof(L"InvalidDataSize"), L"InvalidDataSize");
+    }
+    return EFI_VOLUME_CORRUPTED;
+  }
+  CheckSum32 = CalculateSum32((UINT32 *)MicrocodeEntryPoint, DataSize + sizeof(CPU_MICROCODE_HEADER));
+  if (CheckSum32 != 0) {
+    DEBUG((EFI_D_ERROR, "VerifyMicrocode - fail on CheckSum32\n"));
+    *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INVALID_FORMAT;
+    if (AbortReason != NULL) {
+      *AbortReason = AllocateCopyPool(sizeof(L"InvalidChecksum"), L"InvalidChecksum");
+    }
+    return EFI_VOLUME_CORRUPTED;
+  }
+
+  //
+  // Check ProcessorSignature/ProcessorFlags
+  //
+  CorrectMicrocode = FALSE;
+  CurrentProcessorSignature = GetCurrentProcessorSignature();
+  CurrentPlatformId = GetCurrentPlatformId();
+  if ((MicrocodeEntryPoint->ProcessorSignature.Uint32 != CurrentProcessorSignature) ||
+      ((MicrocodeEntryPoint->ProcessorFlags & (1 << CurrentPlatformId)) == 0)) {
+    ExtendedTableLength = TotalSize - (DataSize + sizeof(CPU_MICROCODE_HEADER));
+    if (ExtendedTableLength != 0) {
+      //
+      // Extended Table exist, check if the CPU in support list
+      //
+      ExtendedTableHeader = (CPU_MICROCODE_EXTENDED_TABLE_HEADER *)((UINT8 *)(MicrocodeEntryPoint) + DataSize + sizeof(CPU_MICROCODE_HEADER));
+      //
+      // Calculate Extended Checksum
+      //
+      if ((ExtendedTableLength > sizeof(CPU_MICROCODE_EXTENDED_TABLE_HEADER)) && ((ExtendedTableLength & 0x3) != 0)) {
+        CheckSum32 = CalculateSum32((UINT32 *)ExtendedTableHeader, ExtendedTableLength);
+        if (CheckSum32 == 0) {
+          //
+          // Checksum correct
+          //
+          ExtendedTableCount = ExtendedTableHeader->ExtendedSignatureCount;
+          if (ExtendedTableCount <= (ExtendedTableLength - sizeof(CPU_MICROCODE_EXTENDED_TABLE_HEADER)) / sizeof(CPU_MICROCODE_EXTENDED_TABLE)) {
+            ExtendedTable = (CPU_MICROCODE_EXTENDED_TABLE *)(ExtendedTableHeader + 1);
+            for (Index = 0; Index < ExtendedTableCount; Index++) {
+              CheckSum32 = CalculateSum32((UINT32 *)ExtendedTable, sizeof(CPU_MICROCODE_EXTENDED_TABLE));
+              if (CheckSum32 == 0) {
+                //
+                // Verify Header
+                //
+                if ((ExtendedTable->ProcessorSignature.Uint32 == CurrentProcessorSignature) &&
+                    (ExtendedTable->ProcessorFlag & (1 << CurrentPlatformId))) {
+                  //
+                  // Find one
+                  //
+                  CorrectMicrocode = TRUE;
+                  break;
+                }
+              }
+              ExtendedTable++;
+            }
+          }
+        }
+      }
+    }
+    if (!CorrectMicrocode) {
+      DEBUG((EFI_D_ERROR, "VerifyMicrocode - fail on CurrentProcessorSignature/ProcessorFlags\n"));
+      *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INCORRECT_VERSION;
+      if (AbortReason != NULL) {
+        if (MicrocodeEntryPoint->ProcessorSignature.Uint32 != CurrentProcessorSignature) {
+          *AbortReason = AllocateCopyPool(sizeof(L"UnsupportedProcessSignature"), L"UnsupportedProcessSignature");
+        } else {
+          *AbortReason = AllocateCopyPool(sizeof(L"UnsupportedProcessorFlags"), L"UnsupportedProcessorFlags");
+        }
+      }
+      return EFI_UNSUPPORTED;
+    }
+  }
+
+  //
+  // Check UpdateRevision
+  //
+  CurrentRevision = GetCurrentMicrocodeSignature();
+  if (MicrocodeEntryPoint->UpdateRevision < CurrentRevision) {
+    DEBUG((EFI_D_ERROR, "VerifyMicrocode - fail on UpdateRevision\n"));
+    *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INCORRECT_VERSION;
+    if (AbortReason != NULL) {
+      *AbortReason = AllocateCopyPool(sizeof(L"IncorrectRevision"), L"IncorrectRevision");
+    }
+    return EFI_INCOMPATIBLE_VERSION;
+  }
+
+  //
+  // try load MCU
+  //
+  if (TryLoad) {
+    CurrentRevision = LoadMicrocode((UINTN)MicrocodeEntryPoint + sizeof(CPU_MICROCODE_HEADER));
+    if (MicrocodeEntryPoint->UpdateRevision != CurrentRevision) {
+      DEBUG((EFI_D_ERROR, "VerifyMicrocode - fail on LoadMicrocode\n"));
+      *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_AUTH_ERROR;
+      if (AbortReason != NULL) {
+        *AbortReason = AllocateCopyPool(sizeof(L"InvalidData"), L"InvalidData");
+      }
+      return EFI_SECURITY_VIOLATION;
+    }
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Get current Microcode in used.
+
+  @return current Microcode in used.
+**/
+VOID *
+GetCurrentMicrocodeInUse(
+  VOID
+  )
+{
+  BOOLEAN                                 Result;
+  EFI_STATUS                              Status;
+  UINT64                                  MicrocodePatchAddress;
+  UINT64                                  MicrocodePatchRegionSize;
+  CPU_MICROCODE_HEADER                    *MicrocodeEntryPoint;
+  UINTN                                   MicrocodeEnd;
+  UINTN                                   TotalSize;
+  UINTN                                   Count;
+  UINT32                                  AttemptStatus;
+
+  Result = GetMicrocodeRegion(&MicrocodePatchAddress, &MicrocodePatchRegionSize);
+  if (!Result) {
+    DEBUG((EFI_D_ERROR, "Fail to get Microcode Region\n"));
+    return NULL;
+  }
+  DEBUG((EFI_D_ERROR, "Microcode Region - 0x%lx - 0x%lx\n", MicrocodePatchAddress, MicrocodePatchRegionSize));
+
+  Count = 0;
+
+  MicrocodeEnd = (UINTN)(MicrocodePatchAddress + MicrocodePatchRegionSize);
+  MicrocodeEntryPoint = (CPU_MICROCODE_HEADER *)(UINTN)MicrocodePatchAddress;
+  do {
+    if (MicrocodeEntryPoint->HeaderVersion == 0x1 && MicrocodeEntryPoint->LoaderRevision == 0x1) {
+      //
+      // It is the microcode header. It is not the padding data between microcode patches
+      // becasue the padding data should not include 0x00000001 and it should be the repeated
+      // byte format (like 0xXYXYXYXY....).
+      //
+      if (MicrocodeEntryPoint->DataSize == 0) {
+        TotalSize = 2048;
+      } else {
+        TotalSize = MicrocodeEntryPoint->TotalSize;
+      }
+      Status = VerifyMicrocode(MicrocodeEntryPoint, TotalSize, FALSE, &AttemptStatus, NULL);
+      if (!EFI_ERROR(Status)) {
+        return MicrocodeEntryPoint;
+      }
+
+    } else {
+      //
+      // It is the padding data between the microcode patches for microcode patches alignment.
+      // Because the microcode patch is the multiple of 1-KByte, the padding data should not
+      // exist if the microcode patch alignment value is not larger than 1-KByte. So, the microcode
+      // alignment value should be larger than 1-KByte. We could skip SIZE_1KB padding data to
+      // find the next possible microcode patch header.
+      //
+      MicrocodeEntryPoint = (CPU_MICROCODE_HEADER *)(((UINTN)MicrocodeEntryPoint) + SIZE_1KB);
+      continue;
+    }
+
+    Count++;
+    ASSERT(Count < 0xFF);
+
+    //
+    // Get the next patch.
+    //
+    MicrocodeEntryPoint = (CPU_MICROCODE_HEADER *)(((UINTN)MicrocodeEntryPoint) + TotalSize);
+  } while (((UINTN)MicrocodeEntryPoint < MicrocodeEnd));
+
+  return NULL;
+}
+
+/**
+  Get current Microcode used region size.
+
+  @return current Microcode used region size.
+**/
+UINTN
+GetCurrentMicrocodeUsedRegionSize(
+  VOID
+  )
+{
+  BOOLEAN                                 Result;
+  UINT64                                  MicrocodePatchAddress;
+  UINT64                                  MicrocodePatchRegionSize;
+  CPU_MICROCODE_HEADER                    *MicrocodeEntryPoint;
+  UINTN                                   MicrocodeEnd;
+  UINTN                                   TotalSize;
+  UINTN                                   Count;
+  UINTN                                   MicrocodeUsedEnd;
+
+  Result = GetMicrocodeRegion(&MicrocodePatchAddress, &MicrocodePatchRegionSize);
+  if (!Result) {
+    DEBUG((EFI_D_ERROR, "Fail to get Microcode Region\n"));
+    return 0;
+  }
+  DEBUG((EFI_D_ERROR, "Microcode Region - 0x%lx - 0x%lx\n", MicrocodePatchAddress, MicrocodePatchRegionSize));
+
+  MicrocodeUsedEnd = (UINTN)MicrocodePatchAddress;
+  Count = 0;
+
+  MicrocodeEnd = (UINTN)(MicrocodePatchAddress + MicrocodePatchRegionSize);
+  MicrocodeEntryPoint = (CPU_MICROCODE_HEADER *)(UINTN)MicrocodePatchAddress;
+  do {
+    if (MicrocodeEntryPoint->HeaderVersion == 0x1 && MicrocodeEntryPoint->LoaderRevision == 0x1) {
+      //
+      // It is the microcode header. It is not the padding data between microcode patches
+      // becasue the padding data should not include 0x00000001 and it should be the repeated
+      // byte format (like 0xXYXYXYXY....).
+      //
+      if (MicrocodeEntryPoint->DataSize == 0) {
+        TotalSize = 2048;
+      } else {
+        TotalSize = MicrocodeEntryPoint->TotalSize;
+      }
+
+    } else {
+      //
+      // It is the padding data between the microcode patches for microcode patches alignment.
+      // Because the microcode patch is the multiple of 1-KByte, the padding data should not
+      // exist if the microcode patch alignment value is not larger than 1-KByte. So, the microcode
+      // alignment value should be larger than 1-KByte. We could skip SIZE_1KB padding data to
+      // find the next possible microcode patch header.
+      //
+      MicrocodeEntryPoint = (CPU_MICROCODE_HEADER *)(((UINTN)MicrocodeEntryPoint) + SIZE_1KB);
+      continue;
+    }
+
+    Count++;
+    ASSERT(Count < 0xFF);
+    MicrocodeUsedEnd = (UINTN)MicrocodeEntryPoint;
+
+    //
+    // Get the next patch.
+    //
+    MicrocodeEntryPoint = (CPU_MICROCODE_HEADER *)(((UINTN)MicrocodeEntryPoint) + TotalSize);
+  } while (((UINTN)MicrocodeEntryPoint < MicrocodeEnd));
+
+  return MicrocodeUsedEnd - (UINTN)MicrocodePatchAddress;
+}
+
+/**
+  Update Microcode.
+
+  @param  Address            The flash address of Microcode.
+  @param  Image              The Microcode image buffer.
+  @param  ImageSize          The size of Microcode image buffer in bytes.
+  @param  LastAttemptStatus  The last attempt status, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+
+  @retval EFI_SUCCESS           The Microcode image is updated.
+  @retval EFI_WRITE_PROTECTED   The flash device is read only.
+**/
+EFI_STATUS
+UpdateMicrocode(
+  IN UINT64  Address,
+  IN VOID    *Image,
+  IN UINTN   ImageSize,
+  OUT UINT32 *LastAttemptStatus
+  )
+{
+  EFI_STATUS  Status;
+
+  DEBUG((EFI_D_INFO, "PlatformUpdate:"));
+  DEBUG((EFI_D_INFO, "  Address - 0x%lx,", Address));
+  DEBUG((EFI_D_INFO, "  Legnth - 0x%x\n", ImageSize));
+
+  Status = MicrocodeFlashWrite (
+             Address,
+             Image,
+             ImageSize
+             );
+  if (!EFI_ERROR(Status)) {
+    *LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;
+  } else {
+    *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL;
+  }
+  return Status;
+}
+
+/**
+  Write Microcode.
+
+  @param  ImageIndex         The index of Microcode image.
+  @param  Image              The Microcode image buffer.
+  @param  ImageSize          The size of Microcode image buffer in bytes.
+  @param  LastAttemptVersion The last attempt version, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+  @param  LastAttemptStatus  The last attempt status, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+  @param  AbortReason        A pointer to a pointer to a null-terminated string providing more
+                             details for the aborted operation. The buffer is allocated by this function
+                             with AllocatePool(), and it is the caller's responsibility to free it with a
+                             call to FreePool().
+
+  @retval EFI_SUCCESS               The Microcode image is written.
+  @retval EFI_VOLUME_CORRUPTED      The Microcode image is corrupt.
+  @retval EFI_INCOMPATIBLE_VERSION  The Microcode image version is incorrect.
+  @retval EFI_SECURITY_VIOLATION    The Microcode image fails to load.
+  @retval EFI_WRITE_PROTECTED   The flash device is read only.
+**/
+EFI_STATUS
+MicrocodeWrite(
+  IN  UINTN  ImageIndex,
+  IN  VOID   *Image,
+  IN  UINTN  ImageSize,
+  OUT UINT32 *LastAttemptVersion,
+  OUT UINT32 *LastAttemptStatus,
+  OUT CHAR16 **AbortReason
+  )
+{
+  BOOLEAN                                 Result;
+  EFI_STATUS                              Status;
+  UINT64                                  MicrocodePatchAddress;
+  UINT64                                  MicrocodePatchRegionSize;
+  CPU_MICROCODE_HEADER                    *CurrentMicrocodeEntryPoint;
+  UINTN                                   CurrentTotalSize;
+  UINTN                                   UsedRegionSize;
+  VOID                                    *AlignedImage;
+
+  Result = GetMicrocodeRegion(&MicrocodePatchAddress, &MicrocodePatchRegionSize);
+  if (!Result) {
+    DEBUG((EFI_D_ERROR, "Fail to get Microcode Region\n"));
+    return EFI_NOT_FOUND;
+  }
+
+  CurrentTotalSize = 0;
+  CurrentMicrocodeEntryPoint = GetCurrentMicrocodeInUse();
+  if (CurrentMicrocodeEntryPoint != NULL) {
+    if (CurrentMicrocodeEntryPoint->DataSize == 0) {
+      CurrentTotalSize = 2048;
+    } else {
+      CurrentTotalSize = CurrentMicrocodeEntryPoint->TotalSize;
+    }
+  }
+
+  //
+  // MCU must be 16 bytes aligned
+  //
+  AlignedImage = AllocateCopyPool(ImageSize, Image);
+
+  *LastAttemptVersion = ((CPU_MICROCODE_HEADER *)Image)->UpdateRevision;
+  Status = VerifyMicrocode(AlignedImage, ImageSize, TRUE, LastAttemptStatus, AbortReason);
+  if (EFI_ERROR(Status)) {
+    DEBUG((EFI_D_ERROR, "Fail to verify Microcode Region\n"));
+    FreePool(AlignedImage);
+    return Status;
+  }
+  DEBUG((EFI_D_INFO, "Pass VerifyMicrocode\n"));
+
+  if (CurrentTotalSize < ImageSize) {
+    UsedRegionSize = GetCurrentMicrocodeUsedRegionSize();
+    if (MicrocodePatchRegionSize - UsedRegionSize >= ImageSize) {
+      //
+      // Append
+      //
+      DEBUG((EFI_D_INFO, "Append new microcode\n"));
+      Status = UpdateMicrocode(MicrocodePatchAddress + UsedRegionSize, AlignedImage, ImageSize, LastAttemptStatus);
+    } else if (MicrocodePatchRegionSize >= ImageSize) {
+      //
+      // Ignor all others and just add this one from beginning.
+      //
+      DEBUG((EFI_D_INFO, "Add new microcode from beginning\n"));
+      Status = UpdateMicrocode(MicrocodePatchAddress, AlignedImage, ImageSize, LastAttemptStatus);
+    } else {
+      DEBUG((EFI_D_ERROR, "Microcode too big\n"));
+      *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INSUFFICIENT_RESOURCES;
+      Status = EFI_OUT_OF_RESOURCES;
+    }
+  } else {
+    //
+    // Replace
+    //
+    DEBUG((EFI_D_INFO, "Replace old microcode\n"));
+    Status = UpdateMicrocode((UINTN)CurrentMicrocodeEntryPoint, AlignedImage, ImageSize, LastAttemptStatus);
+  }
+
+  FreePool(AlignedImage);
+
+  return Status;
+}
+
+
diff --git a/UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.h b/UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.h
new file mode 100644
index 0000000..23ec0ba
--- /dev/null
+++ b/UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.h
@@ -0,0 +1,299 @@
+/** @file
+  Microcode update header file.
+
+  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _MICROCODE_FMP_H_
+#define _MICROCODE_FMP_H_
+
+#include <PiDxe.h>
+
+#include <Guid/SystemResourceTable.h>
+#include <Guid/MicrocodeFmp.h>
+
+#include <Protocol/FirmwareManagement.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/DevicePathLib.h>
+#include <Library/HobLib.h>
+#include <Library/MicrocodeFlashAccessLib.h>
+
+#include <Register/Cpuid.h>
+#include <Register/Msr.h>
+#include <Register/Microcode.h>
+
+/**
+  Returns information about the current firmware image(s) of the device.
+
+  This function allows a copy of the current firmware image to be created and saved.
+  The saved copy could later been used, for example, in firmware image recovery or rollback.
+
+  @param[in]      This               A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
+  @param[in, out] ImageInfoSize      A pointer to the size, in bytes, of the ImageInfo buffer.
+                                     On input, this is the size of the buffer allocated by the caller.
+                                     On output, it is the size of the buffer returned by the firmware
+                                     if the buffer was large enough, or the size of the buffer needed
+                                     to contain the image(s) information if the buffer was too small.
+  @param[in, out] ImageInfo          A pointer to the buffer in which firmware places the current image(s)
+                                     information. The information is an array of EFI_FIRMWARE_IMAGE_DESCRIPTORs.
+  @param[out]     DescriptorVersion  A pointer to the location in which firmware returns the version number
+                                     associated with the EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+  @param[out]     DescriptorCount    A pointer to the location in which firmware returns the number of
+                                     descriptors or firmware images within this device.
+  @param[out]     DescriptorSize     A pointer to the location in which firmware returns the size, in bytes,
+                                     of an individual EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+  @param[out]     PackageVersion     A version number that represents all the firmware images in the device.
+                                     The format is vendor specific and new version must have a greater value
+                                     than the old version. If PackageVersion is not supported, the value is
+                                     0xFFFFFFFF. A value of 0xFFFFFFFE indicates that package version comparison
+                                     is to be performed using PackageVersionName. A value of 0xFFFFFFFD indicates
+                                     that package version update is in progress.
+  @param[out]     PackageVersionName A pointer to a pointer to a null-terminated string representing the
+                                     package version name. The buffer is allocated by this function with
+                                     AllocatePool(), and it is the caller's responsibility to free it with a call
+                                     to FreePool().
+
+  @retval EFI_SUCCESS                The device was successfully updated with the new image.
+  @retval EFI_BUFFER_TOO_SMALL       The ImageInfo buffer was too small. The current buffer size
+                                     needed to hold the image(s) information is returned in ImageInfoSize.
+  @retval EFI_INVALID_PARAMETER      ImageInfoSize is NULL.
+  @retval EFI_DEVICE_ERROR           Valid information could not be returned. Possible corrupted image.
+
+**/
+EFI_STATUS
+EFIAPI
+FmpGetImageInfo(
+  IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL       *This,
+  IN OUT    UINTN                           *ImageInfoSize,
+  IN OUT    EFI_FIRMWARE_IMAGE_DESCRIPTOR   *ImageInfo,
+  OUT       UINT32                          *DescriptorVersion,
+  OUT       UINT8                           *DescriptorCount,
+  OUT       UINTN                           *DescriptorSize,
+  OUT       UINT32                          *PackageVersion,
+  OUT       CHAR16                          **PackageVersionName
+  );
+
+/**
+  Retrieves a copy of the current firmware image of the device.
+
+  This function allows a copy of the current firmware image to be created and saved.
+  The saved copy could later been used, for example, in firmware image recovery or rollback.
+
+  @param[in]     This            A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
+  @param[in]     ImageIndex      A unique number identifying the firmware image(s) within the device.
+                                 The number is between 1 and DescriptorCount.
+  @param[in,out] Image           Points to the buffer where the current image is copied to.
+  @param[in,out] ImageSize       On entry, points to the size of the buffer pointed to by Image, in bytes.
+                                 On return, points to the length of the image, in bytes.
+
+  @retval EFI_SUCCESS            The device was successfully updated with the new image.
+  @retval EFI_BUFFER_TOO_SMALL   The buffer specified by ImageSize is too small to hold the
+                                 image. The current buffer size needed to hold the image is returned
+                                 in ImageSize.
+  @retval EFI_INVALID_PARAMETER  The Image was NULL.
+  @retval EFI_NOT_FOUND          The current image is not copied to the buffer.
+  @retval EFI_UNSUPPORTED        The operation is not supported.
+  @retval EFI_SECURITY_VIOLATIO  The operation could not be performed due to an authentication failure.
+
+**/
+EFI_STATUS
+EFIAPI
+FmpGetImage(
+  IN  EFI_FIRMWARE_MANAGEMENT_PROTOCOL  *This,
+  IN  UINT8                             ImageIndex,
+  IN  OUT  VOID                         *Image,
+  IN  OUT  UINTN                        *ImageSize
+  );
+
+/**
+  Updates the firmware image of the device.
+
+  This function updates the hardware with the new firmware image.
+  This function returns EFI_UNSUPPORTED if the firmware image is not updatable.
+  If the firmware image is updatable, the function should perform the following minimal validations
+  before proceeding to do the firmware image update.
+  - Validate the image authentication if image has attribute
+    IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED. The function returns
+    EFI_SECURITY_VIOLATION if the validation fails.
+  - Validate the image is a supported image for this device. The function returns EFI_ABORTED if
+    the image is unsupported. The function can optionally provide more detailed information on
+    why the image is not a supported image.
+  - Validate the data from VendorCode if not null. Image validation must be performed before
+    VendorCode data validation. VendorCode data is ignored or considered invalid if image
+    validation failed. The function returns EFI_ABORTED if the data is invalid.
+
+  VendorCode enables vendor to implement vendor-specific firmware image update policy. Null if
+  the caller did not specify the policy or use the default policy. As an example, vendor can implement
+  a policy to allow an option to force a firmware image update when the abort reason is due to the new
+  firmware image version is older than the current firmware image version or bad image checksum.
+  Sensitive operations such as those wiping the entire firmware image and render the device to be
+  non-functional should be encoded in the image itself rather than passed with the VendorCode.
+  AbortReason enables vendor to have the option to provide a more detailed description of the abort
+  reason to the caller.
+
+  @param[in]  This               A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
+  @param[in]  ImageIndex         A unique number identifying the firmware image(s) within the device.
+                                 The number is between 1 and DescriptorCount.
+  @param[in]  Image              Points to the new image.
+  @param[in]  ImageSize          Size of the new image in bytes.
+  @param[in]  VendorCode         This enables vendor to implement vendor-specific firmware image update policy.
+                                 Null indicates the caller did not specify the policy or use the default policy.
+  @param[in]  Progress           A function used by the driver to report the progress of the firmware update.
+  @param[out] AbortReason        A pointer to a pointer to a null-terminated string providing more
+                                 details for the aborted operation. The buffer is allocated by this function
+                                 with AllocatePool(), and it is the caller's responsibility to free it with a
+                                 call to FreePool().
+
+  @retval EFI_SUCCESS            The device was successfully updated with the new image.
+  @retval EFI_ABORTED            The operation is aborted.
+  @retval EFI_INVALID_PARAMETER  The Image was NULL.
+  @retval EFI_UNSUPPORTED        The operation is not supported.
+  @retval EFI_SECURITY_VIOLATIO  The operation could not be performed due to an authentication failure.
+
+**/
+EFI_STATUS
+EFIAPI
+FmpSetImage(
+  IN  EFI_FIRMWARE_MANAGEMENT_PROTOCOL                 *This,
+  IN  UINT8                                            ImageIndex,
+  IN  CONST VOID                                       *Image,
+  IN  UINTN                                            ImageSize,
+  IN  CONST VOID                                       *VendorCode,
+  IN  EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS    Progress,
+  OUT CHAR16                                           **AbortReason
+  );
+
+/**
+  Checks if the firmware image is valid for the device.
+
+  This function allows firmware update application to validate the firmware image without
+  invoking the SetImage() first.
+
+  @param[in]  This               A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
+  @param[in]  ImageIndex         A unique number identifying the firmware image(s) within the device.
+                                 The number is between 1 and DescriptorCount.
+  @param[in]  Image              Points to the new image.
+  @param[in]  ImageSize          Size of the new image in bytes.
+  @param[out] ImageUpdatable     Indicates if the new image is valid for update. It also provides,
+                                 if available, additional information if the image is invalid.
+
+  @retval EFI_SUCCESS            The image was successfully checked.
+  @retval EFI_INVALID_PARAMETER  The Image was NULL.
+  @retval EFI_UNSUPPORTED        The operation is not supported.
+  @retval EFI_SECURITY_VIOLATIO  The operation could not be performed due to an authentication failure.
+
+**/
+EFI_STATUS
+EFIAPI
+FmpCheckImage(
+  IN  EFI_FIRMWARE_MANAGEMENT_PROTOCOL  *This,
+  IN  UINT8                             ImageIndex,
+  IN  CONST VOID                        *Image,
+  IN  UINTN                             ImageSize,
+  OUT UINT32                            *ImageUpdatable
+  );
+
+/**
+  Returns information about the firmware package.
+
+  This function returns package information.
+
+  @param[in]  This                     A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
+  @param[out] PackageVersion           A version number that represents all the firmware images in the device.
+                                       The format is vendor specific and new version must have a greater value
+                                       than the old version. If PackageVersion is not supported, the value is
+                                       0xFFFFFFFF. A value of 0xFFFFFFFE indicates that package version
+                                       comparison is to be performed using PackageVersionName. A value of
+                                       0xFFFFFFFD indicates that package version update is in progress.
+  @param[out] PackageVersionName       A pointer to a pointer to a null-terminated string representing
+                                       the package version name. The buffer is allocated by this function with
+                                       AllocatePool(), and it is the caller's responsibility to free it with a
+                                       call to FreePool().
+  @param[out] PackageVersionNameMaxLen The maximum length of package version name if device supports update of
+                                       package version name. A value of 0 indicates the device does not support
+                                       update of package version name. Length is the number of Unicode characters,
+                                       including the terminating null character.
+  @param[out] AttributesSupported      Package attributes that are supported by this device. See 'Package Attribute
+                                       Definitions' for possible returned values of this parameter. A value of 1
+                                       indicates the attribute is supported and the current setting value is
+                                       indicated in AttributesSetting. A value of 0 indicates the attribute is not
+                                       supported and the current setting value in AttributesSetting is meaningless.
+  @param[out] AttributesSetting        Package attributes. See 'Package Attribute Definitions' for possible returned
+                                       values of this parameter
+
+  @retval EFI_SUCCESS                  The package information was successfully returned.
+  @retval EFI_UNSUPPORTED              The operation is not supported.
+
+**/
+EFI_STATUS
+EFIAPI
+FmpGetPackageInfo(
+  IN  EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This,
+  OUT UINT32                           *PackageVersion,
+  OUT CHAR16                           **PackageVersionName,
+  OUT UINT32                           *PackageVersionNameMaxLen,
+  OUT UINT64                           *AttributesSupported,
+  OUT UINT64                           *AttributesSetting
+  );
+
+/**
+  Updates information about the firmware package.
+
+  This function updates package information.
+  This function returns EFI_UNSUPPORTED if the package information is not updatable.
+  VendorCode enables vendor to implement vendor-specific package information update policy.
+  Null if the caller did not specify this policy or use the default policy.
+
+  @param[in]  This               A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
+  @param[in]  Image              Points to the authentication image.
+                                 Null if authentication is not required.
+  @param[in]  ImageSize          Size of the authentication image in bytes.
+                                 0 if authentication is not required.
+  @param[in]  VendorCode         This enables vendor to implement vendor-specific firmware
+                                 image update policy.
+                                 Null indicates the caller did not specify this policy or use
+                                 the default policy.
+  @param[in]  PackageVersion     The new package version.
+  @param[in]  PackageVersionName A pointer to the new null-terminated Unicode string representing
+                                 the package version name.
+                                 The string length is equal to or less than the value returned in
+                                 PackageVersionNameMaxLen.
+
+  @retval EFI_SUCCESS            The device was successfully updated with the new package
+                                 information.
+  @retval EFI_INVALID_PARAMETER  The PackageVersionName length is longer than the value
+                                 returned in PackageVersionNameMaxLen.
+  @retval EFI_UNSUPPORTED        The operation is not supported.
+  @retval EFI_SECURITY_VIOLATIO  The operation could not be performed due to an authentication failure.
+
+**/
+EFI_STATUS
+EFIAPI
+FmpSetPackageInfo(
+  IN  EFI_FIRMWARE_MANAGEMENT_PROTOCOL   *This,
+  IN  CONST VOID                         *Image,
+  IN  UINTN                              ImageSize,
+  IN  CONST VOID                         *VendorCode,
+  IN  UINT32                             PackageVersion,
+  IN  CONST CHAR16                       *PackageVersionName
+  );
+
+#endif
+
diff --git a/UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.inf b/UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.inf
new file mode 100644
index 0000000..736684c
--- /dev/null
+++ b/UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.inf
@@ -0,0 +1,68 @@
+## @file
+# Microcode FMP update driver.
+#
+# Produce FMP instance to update Microcode.
+#
+#  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = MicrocodeUpdate
+  MODULE_UNI_FILE                = MicrocodeUpdateDxe.uni
+  FILE_GUID                      = 0565365C-2FE1-4F88-B3BE-624C04623A20
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = MicrocodeFmpMain
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = X64
+#
+
+[Sources]
+  MicrocodeFmp.c
+  MicrocodeUpdate.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  UefiCpuPkg/UefiCpuPkg.dec
+
+[LibraryClasses]
+  BaseLib
+  UefiLib
+  BaseMemoryLib
+  DebugLib
+  PcdLib
+  MemoryAllocationLib
+  UefiBootServicesTableLib
+  HobLib
+  UefiRuntimeServicesTableLib
+  UefiDriverEntryPoint
+  MicrocodeFlashAccessLib
+
+[Guids]
+  gMicrocodeFmpImageTypeIdGuid
+
+[Protocols]
+  gEfiFirmwareManagementProtocolGuid            ## SOMTIMES_PRODUCE
+
+[Pcd]
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuMicrocodePatchAddress            ## CONSUMES
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuMicrocodePatchRegionSize         ## CONSUMES
+
+[Depex]
+  gEfiVariableArchProtocolGuid
+
+[UserExtensions.TianoCore."ExtraFiles"]
+  MicrocodeUpdateDxeExtra.uni
+
diff --git a/UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdateDxe.uni b/UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdateDxe.uni
new file mode 100644
index 0000000..1b0d494
--- /dev/null
+++ b/UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdateDxe.uni
@@ -0,0 +1,21 @@
+// /** @file
+// Microcode FMP update driver.
+//
+// Produce FMP instance to update Microcode.
+//
+// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+//
+// This program and the accompanying materials
+// are licensed and made available under the terms and conditions of the BSD License
+// which accompanies this distribution.  The full text of the license may be found at
+// http://opensource.org/licenses/bsd-license.php
+//
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT             #language en-US "Microcode FMP update driver."
+
+#string STR_MODULE_DESCRIPTION          #language en-US "Produce FMP instance to update Microcode."
diff --git a/UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdateDxeExtra.uni b/UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdateDxeExtra.uni
new file mode 100644
index 0000000..b667f12
--- /dev/null
+++ b/UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdateDxeExtra.uni
@@ -0,0 +1,20 @@
+// /** @file
+// MicrocodeUpdateDxe Localized Strings and Content
+//
+// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+//
+// This program and the accompanying materials
+// are licensed and made available under the terms and conditions of the BSD License
+// which accompanies this distribution.  The full text of the license may be found at
+// http://opensource.org/licenses/bsd-license.php
+//
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+// **/
+
+#string STR_PROPERTIES_MODULE_NAME
+#language en-US
+"MicrocodeUpdate DXE Driver"
+
+
-- 
2.7.4.windows.1



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

* [PATCH 28/45] UefiCpuPkg/MicrocodeFlashAccessLib: Add NULL MicrocodeFlashAccessLib.
  2016-09-21  6:44 [PATCH 00/45] Add capsule update and recovery sample Jiewen Yao
                   ` (26 preceding siblings ...)
  2016-09-21  6:45 ` [PATCH 27/45] UefiCpuPkg/MicrocodeUpdate: Add MicrocodeUpdate component Jiewen Yao
@ 2016-09-21  6:45 ` Jiewen Yao
  2016-09-21  6:45 ` [PATCH 29/45] UefiCpuPkg/MicrocodeCapsuleApp: Add MicrocodeCapsuleApp application Jiewen Yao
                   ` (20 subsequent siblings)
  48 siblings, 0 replies; 83+ messages in thread
From: Jiewen Yao @ 2016-09-21  6:45 UTC (permalink / raw)
  To: edk2-devel
  Cc: Jeff Fan, Feng Tian, Star Zeng, Michael D Kinney, Liming Gao,
	Chao Zhang

Add NULL instance to pass build.

Cc: Jeff Fan <jeff.fan@intel.com>
Cc: Feng Tian <feng.tian@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Chao Zhang <chao.b.zhang@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
---
 UefiCpuPkg/Library/MicrocodeFlashAccessLibNull/MicrocodeFlashAccessLibNull.c   | 42 ++++++++++++++++++++
 UefiCpuPkg/Library/MicrocodeFlashAccessLibNull/MicrocodeFlashAccessLibNull.inf | 40 +++++++++++++++++++
 UefiCpuPkg/Library/MicrocodeFlashAccessLibNull/MicrocodeFlashAccessLibNull.uni | 21 ++++++++++
 3 files changed, 103 insertions(+)

diff --git a/UefiCpuPkg/Library/MicrocodeFlashAccessLibNull/MicrocodeFlashAccessLibNull.c b/UefiCpuPkg/Library/MicrocodeFlashAccessLibNull/MicrocodeFlashAccessLibNull.c
new file mode 100644
index 0000000..1d8312a
--- /dev/null
+++ b/UefiCpuPkg/Library/MicrocodeFlashAccessLibNull/MicrocodeFlashAccessLibNull.c
@@ -0,0 +1,42 @@
+/** @file
+  Microcode flash device access library NULL instance.
+
+  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <PiDxe.h>
+
+#include <Library/BaseMemoryLib.h>
+#include <Library/MicrocodeFlashAccessLib.h>
+
+/**
+  Perform microcode write opreation.
+
+  @param FlashAddress      The address of flash device to be accessed.
+  @param Buffer            The pointer to the data buffer.
+  @param Length            The length of data buffer in bytes.
+
+  @retval EFI_SUCCESS           The operation returns successfully.
+  @retval EFI_WRITE_PROTECTED   The flash device is read only.
+  @retval EFI_UNSUPPORTED       The flash device access is unsupported.
+  @retval EFI_INVALID_PARAMETER The input parameter is not valid.
+**/
+EFI_STATUS
+EFIAPI
+MicrocodeFlashWrite(
+  IN EFI_PHYSICAL_ADDRESS         FlashAddress,
+  IN VOID                         *Buffer,
+  IN UINTN                        Length
+  )
+{
+  CopyMem((VOID *)(UINTN)(FlashAddress), Buffer, Length);
+  return EFI_SUCCESS;
+}
diff --git a/UefiCpuPkg/Library/MicrocodeFlashAccessLibNull/MicrocodeFlashAccessLibNull.inf b/UefiCpuPkg/Library/MicrocodeFlashAccessLibNull/MicrocodeFlashAccessLibNull.inf
new file mode 100644
index 0000000..a4a47e0
--- /dev/null
+++ b/UefiCpuPkg/Library/MicrocodeFlashAccessLibNull/MicrocodeFlashAccessLibNull.inf
@@ -0,0 +1,40 @@
+## @file
+#  Microcode flash device access library.
+#
+#  Microcode flash device access library NULL instance.
+#
+#  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = MicrocodeFlashAccessLibNull
+  MODULE_UNI_FILE                = MicrocodeFlashAccessLibNull.uni
+  FILE_GUID                      = 6F871ADD-9D86-4676-8BAD-68E2E451FC5B
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = MicrocodeFlashAccessLib
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64 IPF EBC
+#
+
+[Sources]
+  MicrocodeFlashAccessLibNull.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  UefiCpuPkg/UefiCpuPkg.dec
+
+[LibraryClasses]
+  BaseMemoryLib
diff --git a/UefiCpuPkg/Library/MicrocodeFlashAccessLibNull/MicrocodeFlashAccessLibNull.uni b/UefiCpuPkg/Library/MicrocodeFlashAccessLibNull/MicrocodeFlashAccessLibNull.uni
new file mode 100644
index 0000000..cc4195c
--- /dev/null
+++ b/UefiCpuPkg/Library/MicrocodeFlashAccessLibNull/MicrocodeFlashAccessLibNull.uni
@@ -0,0 +1,21 @@
+// /** @file
+//  Microcode flash device access library.
+//
+//  Microcode flash device access library NULL instance.
+//
+// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+//
+// This program and the accompanying materials
+// are licensed and made available under the terms and conditions of the BSD License
+// which accompanies this distribution. The full text of the license may be found at
+// http://opensource.org/licenses/bsd-license.php
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT             #language en-US "Microcode flash device access library."
+
+#string STR_MODULE_DESCRIPTION          #language en-US "Microcode flash device access library NULL instance."
+
-- 
2.7.4.windows.1



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

* [PATCH 29/45] UefiCpuPkg/MicrocodeCapsuleApp: Add MicrocodeCapsuleApp application.
  2016-09-21  6:44 [PATCH 00/45] Add capsule update and recovery sample Jiewen Yao
                   ` (27 preceding siblings ...)
  2016-09-21  6:45 ` [PATCH 28/45] UefiCpuPkg/MicrocodeFlashAccessLib: Add NULL MicrocodeFlashAccessLib Jiewen Yao
@ 2016-09-21  6:45 ` Jiewen Yao
  2016-09-21  6:45 ` [PATCH 30/45] UefiCpuPkg/UefiCpuPkg.dsc: Add MicrocodeCapsule related component Jiewen Yao
                   ` (19 subsequent siblings)
  48 siblings, 0 replies; 83+ messages in thread
From: Jiewen Yao @ 2016-09-21  6:45 UTC (permalink / raw)
  To: edk2-devel
  Cc: Jeff Fan, Feng Tian, Star Zeng, Michael D Kinney, Liming Gao,
	Chao Zhang

This MicrocodeCapsuleApp can help generate Microcode FMP capsule.
It can also dump Microcode capsule information.

Cc: Jeff Fan <jeff.fan@intel.com>
Cc: Feng Tian <feng.tian@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Chao Zhang <chao.b.zhang@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
---
 UefiCpuPkg/Application/MicrocodeCapsuleApp/AppSupport.c                 | 480 ++++++++++++++++++++
 UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.c        | 283 ++++++++++++
 UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.inf      |  62 +++
 UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.uni      |  22 +
 UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleAppExtra.uni |  19 +
 UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleDump.c       | 171 +++++++
 6 files changed, 1037 insertions(+)

diff --git a/UefiCpuPkg/Application/MicrocodeCapsuleApp/AppSupport.c b/UefiCpuPkg/Application/MicrocodeCapsuleApp/AppSupport.c
new file mode 100644
index 0000000..365067d
--- /dev/null
+++ b/UefiCpuPkg/Application/MicrocodeCapsuleApp/AppSupport.c
@@ -0,0 +1,480 @@
+/** @file
+  A shell application that triggers capsule update process.
+
+  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Uefi.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/UefiLib.h>
+#include <Library/PrintLib.h>
+#include <Protocol/LoadedImage.h>
+#include <Protocol/SimpleFileSystem.h>
+#include <Guid/FileInfo.h>
+#include <Guid/Gpt.h>
+
+#define MAX_ARG_NUM     11
+
+UINTN  Argc = 0;
+CHAR16 *Argv[MAX_ARG_NUM];
+CHAR16 *ArgBuffer;
+
+/**
+
+  This function parse application ARG.
+
+  @return Status
+**/
+EFI_STATUS
+GetArg (
+  VOID
+  )
+{
+  UINT8                         *Data;
+  UINTN                         DataSize;
+  CHAR16                        *Index;
+  CHAR16                        *End;
+  CHAR16                        *DIndex;
+  EFI_STATUS                    Status;
+  EFI_LOADED_IMAGE_PROTOCOL     *LoadedImage;
+
+  Status = gBS->HandleProtocol (
+                  gImageHandle,
+                  &gEfiLoadedImageProtocolGuid,
+                  (VOID**)&LoadedImage
+                  );
+  if (EFI_ERROR(Status)) {
+    return Status;
+  }
+
+  Data = LoadedImage->LoadOptions;
+  DataSize = LoadedImage->LoadOptionsSize;
+
+  End = (CHAR16*)(UINTN)(Data + DataSize);
+  Status = gBS->AllocatePool (EfiBootServicesData, DataSize, (VOID **)&ArgBuffer);
+  ASSERT_EFI_ERROR (Status);
+  DIndex = ArgBuffer;
+  Argv[Argc++] = ArgBuffer;
+  for (Index = (CHAR16*)Data; Index < End; ) {
+    if (*Index == L' ') {
+      *DIndex = L'\0';
+      if (Argc >= MAX_ARG_NUM) {
+        return EFI_UNSUPPORTED;
+      }
+      Argv[Argc++] = (++ DIndex);
+      while(*Index == L' ') {
+        Index ++;
+      }
+    }
+    (*(DIndex ++)) = (*(Index ++));
+  }
+  return EFI_SUCCESS;
+}
+
+/**
+  Clear APP ARG.
+**/
+VOID
+CleanArg (
+  VOID
+  )
+{
+  FreePool (Argv[0]);
+}
+
+/**
+  Return File System Volume containing this shell application.
+
+  @return File System Volume containing this shell application.
+**/
+EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *
+GetMyVol (
+  VOID
+  )
+{
+  EFI_STATUS                        Status;
+  EFI_LOADED_IMAGE_PROTOCOL         *LoadedImage;
+  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Vol;
+
+  Status = gBS->HandleProtocol (
+                  gImageHandle,
+                  &gEfiLoadedImageProtocolGuid,
+                  (VOID **)&LoadedImage
+                  );
+  ASSERT_EFI_ERROR (Status);
+
+  Status = gBS->HandleProtocol (
+                  LoadedImage->DeviceHandle,
+                  &gEfiSimpleFileSystemProtocolGuid,
+                  (VOID **)&Vol
+                  );
+  if (!EFI_ERROR (Status)) {
+    return Vol;
+  }
+
+  return NULL;
+}
+
+/**
+  Read a file from this volume.
+
+  @param Vol             File System Volume
+  @param FileName        The file to be read.
+  @param BufferSize      The file buffer size
+  @param Buffer          The file buffer
+
+  @retval EFI_SUCCESS    Read file successfully
+  @retval EFI_NOT_FOUND  File not found
+**/
+EFI_STATUS
+ReadFileFromVol (
+  IN  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Vol,
+  IN  CHAR16                            *FileName,
+  OUT UINTN                             *BufferSize,
+  OUT VOID                              **Buffer
+  )
+{
+  EFI_STATUS                        Status;
+  EFI_FILE_HANDLE                   RootDir;
+  EFI_FILE_HANDLE                   Handle;
+  UINTN                             FileInfoSize;
+  EFI_FILE_INFO                     *FileInfo;
+  UINTN                             TempBufferSize;
+  VOID                              *TempBuffer;
+
+  //
+  // Open the root directory
+  //
+  Status = Vol->OpenVolume (Vol, &RootDir);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Open the file
+  //
+  Status = RootDir->Open (
+                      RootDir,
+                      &Handle,
+                      FileName,
+                      EFI_FILE_MODE_READ,
+                      0
+                      );
+  if (EFI_ERROR (Status)) {
+    RootDir->Close (RootDir);
+    return Status;
+  }
+
+  RootDir->Close (RootDir);
+
+  //
+  // Get the file information
+  //
+  FileInfoSize = sizeof(EFI_FILE_INFO) + 1024;
+
+  FileInfo = AllocateZeroPool (FileInfoSize);
+  if (FileInfo == NULL) {
+    Handle->Close (Handle);
+    return Status;
+  }
+
+  Status = Handle->GetInfo (
+                     Handle,
+                     &gEfiFileInfoGuid,
+                     &FileInfoSize,
+                     FileInfo
+                     );
+  if (EFI_ERROR (Status)) {
+    Handle->Close (Handle);
+    gBS->FreePool (FileInfo);
+    return Status;
+  }
+
+  //
+  // Allocate buffer for the file data. The last CHAR16 is for L'\0'
+  //
+  TempBufferSize = (UINTN) FileInfo->FileSize + sizeof(CHAR16);
+  TempBuffer = AllocateZeroPool (TempBufferSize);
+  if (TempBuffer == NULL) {
+    Handle->Close (Handle);
+    gBS->FreePool (FileInfo);
+    return Status;
+  }
+
+  gBS->FreePool (FileInfo);
+
+  //
+  // Read the file data to the buffer
+  //
+  Status = Handle->Read (
+                     Handle,
+                     &TempBufferSize,
+                     TempBuffer
+                     );
+  if (EFI_ERROR (Status)) {
+    Handle->Close (Handle);
+    gBS->FreePool (TempBuffer);
+    return Status;
+  }
+
+  Handle->Close (Handle);
+
+  *BufferSize = TempBufferSize;
+  *Buffer     = TempBuffer;
+  return EFI_SUCCESS;
+}
+
+/**
+  Read a file.
+  If ScanFs is FLASE, it will use this Vol as default Fs.
+  If ScanFs is TRUE, it will scan all FS and check the file.
+    If there is only one file match the name, it will be read.
+    If there is more than one file match the name, it will return Error.
+
+  @param ThisVol         File System Volume
+  @param FileName        The file to be read.
+  @param BufferSize      The file buffer size
+  @param Buffer          The file buffer
+  @param ScanFs          Need Scan all FS
+
+  @retval EFI_SUCCESS    Read file successfully
+  @retval EFI_NOT_FOUND  File not found
+  @retval EFI_NO_MAPPING There is duplicated files found
+**/
+EFI_STATUS
+ReadFileToBufferEx (
+  IN OUT EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   **ThisVol,
+  IN  CHAR16                               *FileName,
+  OUT UINTN                                *BufferSize,
+  OUT VOID                                 **Buffer,
+  IN  BOOLEAN                              ScanFs
+  )
+{
+  EFI_STATUS                        Status;
+  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Vol;
+  UINTN                             TempBufferSize;
+  VOID                              *TempBuffer;
+  UINTN                             NoHandles;
+  EFI_HANDLE                        *HandleBuffer;
+  UINTN                             Index;
+
+  //
+  // Check parameters
+  //
+  if ((FileName == NULL) || (Buffer == NULL) || (ThisVol == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // not scan fs
+  //
+  if (!ScanFs) {
+    if (*ThisVol == NULL) {
+      *ThisVol = GetMyVol ();
+      if (*ThisVol == NULL) {
+        return EFI_INVALID_PARAMETER;
+      }
+    }
+    //
+    // Read file directly from Vol
+    //
+    return ReadFileFromVol (*ThisVol, FileName, BufferSize, Buffer);
+  }
+
+  //
+  // need scan fs
+  //
+
+  //
+  // Get all Vol handle
+  //
+  Status = gBS->LocateHandleBuffer (
+                   ByProtocol,
+                   &gEfiSimpleFileSystemProtocolGuid,
+                   NULL,
+                   &NoHandles,
+                   &HandleBuffer
+                   );
+  if (EFI_ERROR (Status) && (NoHandles == 0)) {
+    return EFI_NOT_FOUND;
+  }
+
+  //
+  // Walk through each Vol
+  //
+  *ThisVol = NULL;
+  *BufferSize = 0;
+  *Buffer     = NULL;
+  for (Index = 0; Index < NoHandles; Index++) {
+    Status = gBS->HandleProtocol (
+                    HandleBuffer[Index],
+                    &gEfiSimpleFileSystemProtocolGuid,
+                    (VOID **)&Vol
+                    );
+    if (EFI_ERROR(Status)) {
+      continue;
+    }
+
+    Status = ReadFileFromVol (Vol, FileName, &TempBufferSize, &TempBuffer);
+    if (!EFI_ERROR (Status)) {
+      //
+      // Read file OK, check duplication
+      //
+      if (*ThisVol != NULL) {
+        //
+        // Find the duplicated file
+        //
+        gBS->FreePool (TempBuffer);
+        gBS->FreePool (*Buffer);
+        Print (L"Duplicated FileName found!\n");
+        return EFI_NO_MAPPING;
+      } else {
+        //
+        // Record value
+        //
+        *ThisVol = Vol;
+        *BufferSize = TempBufferSize;
+        *Buffer     = TempBuffer;
+      }
+    }
+  }
+
+  //
+  // Scan Fs done
+  //
+  if (*ThisVol == NULL) {
+    return EFI_NOT_FOUND;
+  }
+
+  //
+  // Done
+  //
+  return EFI_SUCCESS;
+}
+
+/**
+  Read a file.
+
+  @param FileName        The file to be read.
+  @param BufferSize      The file buffer size
+  @param Buffer          The file buffer
+
+  @retval EFI_SUCCESS    Read file successfully
+  @retval EFI_NOT_FOUND  File not found
+**/
+EFI_STATUS
+ReadFileToBuffer (
+  IN  CHAR16                               *FileName,
+  OUT UINTN                                *BufferSize,
+  OUT VOID                                 **Buffer
+  )
+{
+  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Vol;
+  Vol = NULL;
+  return ReadFileToBufferEx(&Vol, FileName, BufferSize, Buffer, FALSE);
+}
+
+/**
+  Write a file.
+
+  @param FileName        The file to be written.
+  @param BufferSize      The file buffer size
+  @param Buffer          The file buffer
+
+  @retval EFI_SUCCESS    Write file successfully
+**/
+EFI_STATUS
+WriteFileFromBuffer(
+  IN  CHAR16                               *FileName,
+  IN  UINTN                                BufferSize,
+  IN  VOID                                 *Buffer
+  )
+{
+  EFI_STATUS                        Status;
+  EFI_FILE_HANDLE                   RootDir;
+  EFI_FILE_HANDLE                   Handle;
+  UINTN                             TempBufferSize;
+  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Vol;
+
+  Vol = GetMyVol();
+
+  //
+  // Open the root directory
+  //
+  Status = Vol->OpenVolume (Vol, &RootDir);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Open the file
+  //
+  Status = RootDir->Open (
+                      RootDir,
+                      &Handle,
+                      FileName,
+                      EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE| EFI_FILE_MODE_CREATE,
+                      0
+                      );
+  if (EFI_ERROR (Status)) {
+    RootDir->Close (RootDir);
+    return Status;
+  }
+
+  //
+  // Delete file
+  //
+  Status = Handle->Delete(Handle);
+  if (EFI_ERROR(Status)) {
+    return Status;
+  }
+
+  //
+  // Open the file again
+  //
+  Status = RootDir->Open (
+                      RootDir,
+                      &Handle,
+                      FileName,
+                      EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE| EFI_FILE_MODE_CREATE,
+                      0
+                      );
+  if (EFI_ERROR (Status)) {
+    RootDir->Close (RootDir);
+    return Status;
+  }
+
+  RootDir->Close (RootDir);
+
+  //
+  // Write the file data from the buffer
+  //
+  TempBufferSize = BufferSize;
+  Status = Handle->Write (
+                     Handle,
+                     &TempBufferSize,
+                     Buffer
+                     );
+  if (EFI_ERROR (Status)) {
+    Handle->Close (Handle);
+    return Status;
+  }
+
+  Handle->Close (Handle);
+
+  return EFI_SUCCESS;
+}
+
diff --git a/UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.c b/UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.c
new file mode 100644
index 0000000..bb79b98
--- /dev/null
+++ b/UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.c
@@ -0,0 +1,283 @@
+/** @file
+  A shell application that generates Microcode FMP capsule update process.
+
+  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Uefi.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/UefiLib.h>
+#include <Library/PrintLib.h>
+#include <Protocol/LoadedImage.h>
+#include <Protocol/SimpleFileSystem.h>
+#include <Guid/FileInfo.h>
+#include <Guid/FmpCapsule.h>
+#include <Guid/MicrocodeFmp.h>
+
+#define CAPSULE_HEADER_SIZE  0x20
+
+#define MAJOR_VERSION   1
+#define MINOR_VERSION   0
+
+#define MAX_ARG_NUM     11
+#define MAX_CAPSULE_NUM (MAX_ARG_NUM - 1)
+
+extern UINTN  Argc;
+extern CHAR16 *Argv[];
+
+/**
+  Dump capsule information
+
+  @retval EFI_SUCCESS            The capsule information is dumped.
+  @retval EFI_UNSUPPORTED        Input parameter is not valid.
+**/
+EFI_STATUS
+DumpCapsule(
+  VOID
+  );
+
+/**
+  Read a file.
+
+  @param FileName        The file to be read.
+  @param BufferSize      The file buffer size
+  @param Buffer          The file buffer
+
+  @retval EFI_SUCCESS    Read file successfully
+  @retval EFI_NOT_FOUND  File not found
+**/
+EFI_STATUS
+ReadFileToBuffer(
+  IN  CHAR16                               *FileName,
+  OUT UINTN                                *BufferSize,
+  OUT VOID                                 **Buffer
+  );
+
+/**
+  Write a file.
+
+  @param FileName        The file to be written.
+  @param BufferSize      The file buffer size
+  @param Buffer          The file buffer
+
+  @retval EFI_SUCCESS    Write file successfully
+**/
+EFI_STATUS
+WriteFileFromBuffer(
+  IN  CHAR16                               *FileName,
+  IN  UINTN                                BufferSize,
+  IN  VOID                                 *Buffer
+  );
+
+/**
+
+  This function parse application ARG.
+
+  @return Status
+**/
+EFI_STATUS
+GetArg (
+  VOID
+  );
+
+/**
+  Clear APP ARG.
+**/
+VOID
+CleanArg (
+  VOID
+  );
+
+/**
+  Create Microcode FMP capsule.
+
+  @retval EFI_SUCCESS            The capsule header is appended.
+  @retval EFI_UNSUPPORTED        Input parameter is not valid.
+  @retval EFI_OUT_OF_RESOURCES   No enough resource to create Microcode capsule.
+**/
+EFI_STATUS
+CreateMicrocodeFmp(
+  VOID
+  )
+{
+  CHAR16                                        *OutputCapsuleName;
+  VOID                                          *MicrocodeBuffer[MAX_CAPSULE_NUM];
+  UINTN                                         FileSize[MAX_CAPSULE_NUM];
+  CHAR16                                        *MicrocodeName;
+  UINTN                                         MicrocodeNum;
+  UINTN                                         MicrocodeFirstIndex;
+  UINTN                                         MicrocodeLastIndex;
+  UINTN                                         Index;
+  UINT8                                         *FullFmpBuffer;
+  UINTN                                         FullFmpBufferSize;
+  EFI_CAPSULE_HEADER                            *CapsuleHeader;
+  EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER        *FmpHeader;
+  EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER  *FmpImageHeader;
+  UINT64                                        *ItemOffsetList;
+  EFI_STATUS                                    Status;
+
+  if (StrCmp(Argv[Argc - 2], L"-O") != 0) {
+    Print(L"CapsuleApp: NO output capsule name.\n");
+    return EFI_UNSUPPORTED;
+  }
+  OutputCapsuleName = Argv[Argc - 1];
+
+  MicrocodeFirstIndex = 2;
+  MicrocodeLastIndex = Argc - 3;
+  MicrocodeNum = MicrocodeLastIndex - MicrocodeFirstIndex + 1;
+
+  if (MicrocodeFirstIndex > MicrocodeLastIndex) {
+    Print(L"CapsuleApp: NO Microcode image.\n");
+    CleanArg();
+    return EFI_UNSUPPORTED;
+  }
+  if (MicrocodeNum > MAX_CAPSULE_NUM) {
+    Print(L"CapsuleApp: Too many Microcode images.\n");
+    CleanArg();
+    return EFI_UNSUPPORTED;
+  }
+
+  ZeroMem(&MicrocodeBuffer, sizeof(MicrocodeBuffer));
+  ZeroMem(&FileSize, sizeof(FileSize));
+  FullFmpBuffer = NULL;
+
+  FullFmpBufferSize = CAPSULE_HEADER_SIZE + sizeof(EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER) + sizeof(UINT64) * MicrocodeNum;
+  for (Index = 0; Index < MicrocodeNum; Index++) {
+    MicrocodeName = Argv[MicrocodeFirstIndex + Index];
+    Status = ReadFileToBuffer(MicrocodeName, &FileSize[Index], &MicrocodeBuffer[Index]);
+    if (EFI_ERROR(Status)) {
+      Print(L"CapsuleApp: Microcode image (%s) is not found.\n", MicrocodeName);
+      goto Done;
+    }
+    FullFmpBufferSize += sizeof(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER) + FileSize[Index];
+  }
+
+  FullFmpBuffer = AllocatePool(FullFmpBufferSize);
+  if (FullFmpBuffer == NULL) {
+    Print(L"CapsuleApp: Fmp Buffer size (0x%x) too big.\n", FullFmpBufferSize);
+    Status = EFI_OUT_OF_RESOURCES;
+    goto Done;
+  }
+
+  CapsuleHeader = (EFI_CAPSULE_HEADER *)FullFmpBuffer;
+  CopyGuid(&CapsuleHeader->CapsuleGuid, &gEfiFmpCapsuleGuid);
+  CapsuleHeader->HeaderSize = CAPSULE_HEADER_SIZE;
+  CapsuleHeader->Flags = CAPSULE_FLAGS_PERSIST_ACROSS_RESET | CAPSULE_FLAGS_INITIATE_RESET;
+  CapsuleHeader->CapsuleImageSize = (UINT32)FullFmpBufferSize;
+  ZeroMem(CapsuleHeader + 1, CAPSULE_HEADER_SIZE - sizeof(EFI_CAPSULE_HEADER));
+
+  FmpHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *)((UINT8 *)CapsuleHeader + CapsuleHeader->HeaderSize);
+  FmpHeader->Version = EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION;
+  FmpHeader->EmbeddedDriverCount = 0;
+  FmpHeader->PayloadItemCount = (UINT16)MicrocodeNum;
+  ItemOffsetList = (UINT64 *)(FmpHeader + 1);
+  ItemOffsetList[0] = (UINTN)&ItemOffsetList[FmpHeader->EmbeddedDriverCount + FmpHeader->PayloadItemCount] - (UINTN)FmpHeader;
+  for (Index = 1; Index < MicrocodeNum; Index++) {
+    ItemOffsetList[Index] = ItemOffsetList[Index - 1] + sizeof(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER) + FileSize[Index - 1];
+  }
+
+  FmpImageHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *)(&ItemOffsetList[FmpHeader->EmbeddedDriverCount + FmpHeader->PayloadItemCount]);
+  for (Index = 0; Index < MicrocodeNum; Index++) {
+    FmpImageHeader->Version = EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION;
+    CopyGuid (&FmpImageHeader->UpdateImageTypeId, &gMicrocodeFmpImageTypeIdGuid);
+    FmpImageHeader->UpdateImageIndex = (UINT8)(Index + 1);
+    ZeroMem(FmpImageHeader->reserved_bytes, sizeof(FmpImageHeader->reserved_bytes));
+    FmpImageHeader->UpdateImageSize = (UINT32)FileSize[Index];
+    FmpImageHeader->UpdateVendorCodeSize = 0;
+    FmpImageHeader->UpdateHardwareInstance = 0;
+    CopyMem(FmpImageHeader + 1, MicrocodeBuffer[Index], FileSize[Index]);
+
+    FmpImageHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *)((UINT8 *)FmpImageHeader + sizeof(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER) + FmpImageHeader->UpdateImageSize + FmpImageHeader->UpdateVendorCodeSize);
+  }
+
+  Status = WriteFileFromBuffer(OutputCapsuleName, FullFmpBufferSize, FullFmpBuffer);
+  Print(L"CapsuleApp: Write %s %r\n", OutputCapsuleName, Status);
+
+Done:
+  for (Index = 0; Index < MicrocodeNum; Index++) {
+    if (MicrocodeBuffer[Index] != NULL) {
+      FreePool(MicrocodeBuffer[Index]);
+    }
+  }
+
+  if (FullFmpBuffer != NULL) {
+    FreePool(FullFmpBuffer);
+  }
+
+  return Status;
+}
+
+/**
+  Print APP usage.
+**/
+VOID
+PrintUsage (
+  VOID
+  )
+{
+  Print(L"MicrocodeCapsuleApp:  usage\n");
+  Print(L"  MicrocodeCapsuleApp -U <Microcode...> -O <Capsule>\n");
+  Print(L"  MicrocodeCapsuleApp -D <Capsule>\n");
+  Print(L"Parameter:\n");
+  Print(L"  -U:  Input Microcode binary file name\n");
+  Print(L"  -D:  Dump Capsule\n");
+}
+
+/**
+  Update Capsule image.
+
+  @param[in]  ImageHandle     The image handle.
+  @param[in]  SystemTable     The system table.
+
+  @retval EFI_SUCCESS            Command completed successfully.
+  @retval EFI_INVALID_PARAMETER  Command usage error.
+  @retval EFI_NOT_FOUND          The input file can't be found.
+**/
+EFI_STATUS
+EFIAPI
+UefiMain (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  )
+{
+  EFI_STATUS                    Status;
+
+  Status = GetArg();
+  if (EFI_ERROR(Status)) {
+    PrintUsage();
+    return Status;
+  }
+  if (Argc < 2) {
+    PrintUsage();
+    CleanArg();
+    return EFI_INVALID_PARAMETER;
+  }
+  if (StrCmp(Argv[1], L"-D") == 0) {
+    Status = DumpCapsule();
+    CleanArg();
+    return Status;
+  }
+  if (StrCmp(Argv[1], L"-U") == 0) {
+    Status = CreateMicrocodeFmp();
+    CleanArg();
+    return Status;
+  }
+
+  Status = EFI_UNSUPPORTED;
+  CleanArg();
+
+  return Status;
+}
diff --git a/UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.inf b/UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.inf
new file mode 100644
index 0000000..272e20e
--- /dev/null
+++ b/UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.inf
@@ -0,0 +1,62 @@
+##  @file
+#  A shell application that generates Microcode FMP capsule.
+#
+# This application can generates Microcode FMP capsule. It can also
+# dump Microcode FMP capsule information.
+#
+#  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010006
+  BASE_NAME                      = MicrocodeCapsuleApp
+  MODULE_UNI_FILE                = MicrocodeCapsuleApp.uni
+  FILE_GUID                      = 4CEF31DA-8682-4274-9CC4-AEE7516A5E7B
+  MODULE_TYPE                    = UEFI_APPLICATION
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = UefiMain
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64
+#
+
+[Sources]
+  MicrocodeCapsuleApp.c
+  MicrocodeCapsuleDump.c
+  AppSupport.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  UefiCpuPkg/UefiCpuPkg.dec
+
+[Guids]
+  gEfiFileInfoGuid
+  gEfiFmpCapsuleGuid
+  gMicrocodeFmpImageTypeIdGuid
+
+[Protocols]
+  gEfiLoadedImageProtocolGuid
+  gEfiSimpleFileSystemProtocolGuid
+
+[LibraryClasses]
+  BaseLib
+  UefiApplicationEntryPoint
+  DebugLib
+  MemoryAllocationLib
+  UefiBootServicesTableLib
+  UefiRuntimeServicesTableLib
+  UefiLib
+  PrintLib
+
+[UserExtensions.TianoCore."ExtraFiles"]
+  MicrocodeCapsuleAppExtra.uni
diff --git a/UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.uni b/UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.uni
new file mode 100644
index 0000000..1d13057
--- /dev/null
+++ b/UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.uni
@@ -0,0 +1,22 @@
+// /** @file
+// A shell application that generates Microcode FMP capsule.
+//
+// This application can generates Microcode FMP capsule. It can also
+// dump Microcode FMP capsule information.
+//
+// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+//
+// This program and the accompanying materials
+// are licensed and made available under the terms and conditions of the BSD License
+// which accompanies this distribution. The full text of the license may be found at
+// http://opensource.org/licenses/bsd-license.php
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT             #language en-US "A shell application that generates Microcode FMP capsule."
+
+#string STR_MODULE_DESCRIPTION          #language en-US "This application can generates Microcode FMP capsule. It can also dump Microcode FMP capsule information."
+
diff --git a/UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleAppExtra.uni b/UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleAppExtra.uni
new file mode 100644
index 0000000..3ba1610
--- /dev/null
+++ b/UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleAppExtra.uni
@@ -0,0 +1,19 @@
+// /** @file
+// MicrocodeCapsuleApp Localized Strings and Content
+//
+// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+//
+// This program and the accompanying materials
+// are licensed and made available under the terms and conditions of the BSD License
+// which accompanies this distribution. The full text of the license may be found at
+// http://opensource.org/licenses/bsd-license.php
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+// **/
+
+#string STR_PROPERTIES_MODULE_NAME
+#language en-US
+"MicrocodeCapsule Application"
+
+
diff --git a/UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleDump.c b/UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleDump.c
new file mode 100644
index 0000000..b8c111d
--- /dev/null
+++ b/UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleDump.c
@@ -0,0 +1,171 @@
+/** @file
+  Dump Microcode Capsule image information.
+
+  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <PiDxe.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/UefiLib.h>
+#include <Library/PrintLib.h>
+#include <Guid/FmpCapsule.h>
+#include <Guid/MicrocodeFmp.h>
+#include <Register/Microcode.h>
+
+/**
+  Read a file.
+
+  @param FileName        The file to be read.
+  @param BufferSize      The file buffer size
+  @param Buffer          The file buffer
+
+  @retval EFI_SUCCESS    Read file successfully
+  @retval EFI_NOT_FOUND  File not found
+**/
+EFI_STATUS
+ReadFileToBuffer(
+  IN  CHAR16                               *FileName,
+  OUT UINTN                                *BufferSize,
+  OUT VOID                                 **Buffer
+  );
+
+extern UINTN  Argc;
+extern CHAR16 *Argv[];
+
+/**
+  Dump Microcode FMP capsule.
+
+  @param Image      The Microcode FMP capsule.
+  @param ImageSize  The size of the Microcode FMP capsule in bytes.
+**/
+VOID
+DumpMicrocodeFmpCapsule(
+  IN VOID   *Image,
+  IN UINTN  ImageSize
+  )
+{
+  CPU_MICROCODE_HEADER  *MicrocodeHeader;
+
+  MicrocodeHeader = Image;
+  Print(L"[Microcode]\n");
+  Print(L"  HeaderVersion   - 0x%08x\n", MicrocodeHeader->HeaderVersion);
+  Print(L"  UpdateRevision  - 0x%08x\n", MicrocodeHeader->UpdateRevision);
+  Print(L"  Date            - 0x%08x\n", MicrocodeHeader->Date.Uint32);
+  Print(L"  ProcessorId     - 0x%08x\n", MicrocodeHeader->ProcessorSignature.Uint32);
+  Print(L"  Checksum        - 0x%08x\n", MicrocodeHeader->Checksum);
+  Print(L"  LoaderRevision  - 0x%08x\n", MicrocodeHeader->LoaderRevision);
+  Print(L"  ProcessorFlags  - 0x%08x\n", MicrocodeHeader->ProcessorFlags);
+  Print(L"  DataSize        - 0x%08x\n", MicrocodeHeader->DataSize);
+  Print(L"  TotalSize       - 0x%08x\n", MicrocodeHeader->TotalSize);
+}
+
+/**
+  Dump a Microcode FMP capsule.
+
+  @param  CapsuleHeader  A pointer to CapsuleHeader
+**/
+VOID
+DumpFmpCapsule(
+  IN EFI_CAPSULE_HEADER  *CapsuleHeader
+  )
+{
+  EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER        *FmpCapsuleHeader;
+  UINT64                                        *ItemOffsetList;
+  UINTN                                         Index;
+  UINTN                                         Count;
+  EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER  *FmpImageHeader;
+  VOID                                          *Image;
+
+  Print(L"[FmpCapusule]\n");
+  Print(L"CapsuleHeader:\n");
+  Print(L"  CapsuleGuid      - %g\n", &CapsuleHeader->CapsuleGuid);
+  Print(L"  HeaderSize       - 0x%x\n", CapsuleHeader->HeaderSize);
+  Print(L"  Flags            - 0x%x\n", CapsuleHeader->Flags);
+  Print(L"  CapsuleImageSize - 0x%x\n", CapsuleHeader->CapsuleImageSize);
+
+  FmpCapsuleHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *)((UINT8 *)CapsuleHeader + CapsuleHeader->HeaderSize);
+  ItemOffsetList = (UINT64 *)(FmpCapsuleHeader + 1);
+  Print(L"FmpHeader:\n");
+  Print(L"  Version             - 0x%x\n", FmpCapsuleHeader->Version);
+  Print(L"  EmbeddedDriverCount - 0x%x\n", FmpCapsuleHeader->EmbeddedDriverCount);
+  Print(L"  PayloadItemCount    - 0x%x\n", FmpCapsuleHeader->PayloadItemCount);
+  Count = FmpCapsuleHeader->EmbeddedDriverCount + FmpCapsuleHeader->PayloadItemCount;
+  for (Index = 0; Index < Count; Index++) {
+    Print(L"  Offset[%d]           - 0x%x\n", Index, ItemOffsetList[Index]);
+  }
+
+  for (Index = FmpCapsuleHeader->EmbeddedDriverCount; Index < Count; Index++) {
+    Print(L"FmpPayload[%d] ImageHeader:\n", Index);
+    FmpImageHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *)((UINT8 *)FmpCapsuleHeader + ItemOffsetList[Index]);
+    Print(L"  Version                - 0x%x\n", FmpImageHeader->Version);
+    Print(L"  UpdateImageTypeId      - %g\n", &FmpImageHeader->UpdateImageTypeId);
+    Print(L"  UpdateImageIndex       - 0x%x\n", FmpImageHeader->UpdateImageIndex);
+    Print(L"  UpdateImageSize        - 0x%x\n", FmpImageHeader->UpdateImageSize);
+    Print(L"  UpdateVendorCodeSize   - 0x%x\n", FmpImageHeader->UpdateVendorCodeSize);
+    if (FmpImageHeader->Version >= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {
+      Print(L"  UpdateHardwareInstance - 0x%lx\n", FmpImageHeader->UpdateHardwareInstance);
+    }
+    if (FmpImageHeader->Version >= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {
+      Image = (UINT8 *)(FmpImageHeader + 1);
+    }  else {
+      Image = (UINT8 *)FmpImageHeader + OFFSET_OF(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER, UpdateHardwareInstance);
+    }
+    if (CompareGuid (&FmpImageHeader->UpdateImageTypeId, &gMicrocodeFmpImageTypeIdGuid)) {
+      DumpMicrocodeFmpCapsule(Image, FmpImageHeader->UpdateImageSize);
+    }
+  }
+}
+
+/**
+  Dump capsule information
+
+  @retval EFI_SUCCESS            The capsule information is dumped.
+  @retval EFI_UNSUPPORTED        Input parameter is not valid.
+**/
+EFI_STATUS
+DumpCapsule(
+  VOID
+  )
+{
+  CHAR16                                        *CapsuleName;
+  VOID                                          *Buffer;
+  UINTN                                         FileSize;
+  EFI_CAPSULE_HEADER                            *CapsuleHeader;
+  EFI_STATUS                                    Status;
+
+  if (Argc != 3) {
+    Print(L"CapsuleApp: Invalid Parameter.\n");
+    return EFI_UNSUPPORTED;
+  }
+
+  CapsuleName = Argv[2];
+  Status = ReadFileToBuffer(CapsuleName, &FileSize, &Buffer);
+  if (EFI_ERROR(Status)) {
+    Print(L"CapsuleApp: Capsule (%s) is not found.\n", CapsuleName);
+    goto Done;
+  }
+
+  CapsuleHeader = Buffer;
+
+  if (CompareGuid(&CapsuleHeader->CapsuleGuid, &gEfiFmpCapsuleGuid)) {
+    DumpFmpCapsule(CapsuleHeader);
+  }
+
+Done:
+  FreePool(Buffer);
+  return Status;
+}
+
-- 
2.7.4.windows.1



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

* [PATCH 30/45] UefiCpuPkg/UefiCpuPkg.dsc: Add MicrocodeCapsule related component.
  2016-09-21  6:44 [PATCH 00/45] Add capsule update and recovery sample Jiewen Yao
                   ` (28 preceding siblings ...)
  2016-09-21  6:45 ` [PATCH 29/45] UefiCpuPkg/MicrocodeCapsuleApp: Add MicrocodeCapsuleApp application Jiewen Yao
@ 2016-09-21  6:45 ` Jiewen Yao
  2016-09-21  6:45 ` [PATCH 31/45] QuarkPlatformPkg/PlatformFlashAccessLib: Add instance for capsule update Jiewen Yao
                   ` (18 subsequent siblings)
  48 siblings, 0 replies; 83+ messages in thread
From: Jiewen Yao @ 2016-09-21  6:45 UTC (permalink / raw)
  To: edk2-devel
  Cc: Jeff Fan, Feng Tian, Star Zeng, Michael D Kinney, Liming Gao,
	Chao Zhang

Add Microcode capsule related component to check build.

Cc: Jeff Fan <jeff.fan@intel.com>
Cc: Feng Tian <feng.tian@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Chao Zhang <chao.b.zhang@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
---
 UefiCpuPkg/UefiCpuPkg.dsc | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/UefiCpuPkg/UefiCpuPkg.dsc b/UefiCpuPkg/UefiCpuPkg.dsc
index d4a6673..78316de 100644
--- a/UefiCpuPkg/UefiCpuPkg.dsc
+++ b/UefiCpuPkg/UefiCpuPkg.dsc
@@ -61,6 +61,7 @@
   SmmCpuFeaturesLib|UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLib.inf
   PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
   PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf
+  MicrocodeFlashAccessLib|UefiCpuPkg/Library/MicrocodeFlashAccessLibNull/MicrocodeFlashAccessLibNull.inf
 
 [LibraryClasses.common.SEC]
   PlatformSecLib|UefiCpuPkg/Library/PlatformSecLibNull/PlatformSecLibNull.inf
@@ -128,6 +129,8 @@
   UefiCpuPkg/SecCore/SecCore.inf
   UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf
   UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume2Pei.inf
+  UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.inf
+  UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.inf
 
 [BuildOptions]
   *_*_*_CC_FLAGS = -D DISABLE_NEW_DEPRECATED_INTERFACES
-- 
2.7.4.windows.1



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

* [PATCH 31/45] QuarkPlatformPkg/PlatformFlashAccessLib: Add instance for capsule update.
  2016-09-21  6:44 [PATCH 00/45] Add capsule update and recovery sample Jiewen Yao
                   ` (29 preceding siblings ...)
  2016-09-21  6:45 ` [PATCH 30/45] UefiCpuPkg/UefiCpuPkg.dsc: Add MicrocodeCapsule related component Jiewen Yao
@ 2016-09-21  6:45 ` Jiewen Yao
  2016-09-21  6:45 ` [PATCH 32/45] QuarkPlatformPkg/SystemBiosDescriptor: Add Descriptor " Jiewen Yao
                   ` (17 subsequent siblings)
  48 siblings, 0 replies; 83+ messages in thread
From: Jiewen Yao @ 2016-09-21  6:45 UTC (permalink / raw)
  To: edk2-devel
  Cc: Michael D Kinney, Kelly Steele, Feng Tian, Star Zeng, Liming Gao,
	Chao Zhang

Add PlatformFlashAccessLib for capsule update.

Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Kelly Steele <kelly.steele@intel.com>
Cc: Feng Tian <feng.tian@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Chao Zhang <chao.b.zhang@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
---
 QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLibDxe.c   | 200 ++++++++++++
 QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLibDxe.inf |  52 +++
 QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/SpiFlashDevice.c              | 336 ++++++++++++++++++++
 QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/SpiFlashDevice.h              | 186 +++++++++++
 4 files changed, 774 insertions(+)

diff --git a/QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLibDxe.c b/QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLibDxe.c
new file mode 100644
index 0000000..3ad30b1
--- /dev/null
+++ b/QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLibDxe.c
@@ -0,0 +1,200 @@
+/** @file
+  Platform Flash Access library.
+
+  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <PiDxe.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PlatformFlashAccessLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Protocol/Spi.h>
+
+//
+// SPI default opcode slots
+//
+#define SPI_OPCODE_JEDEC_ID_INDEX        0
+#define SPI_OPCODE_READ_ID_INDEX         1
+#define SPI_OPCODE_WRITE_S_INDEX         2
+#define SPI_OPCODE_WRITE_INDEX           3
+#define SPI_OPCODE_READ_INDEX            4
+#define SPI_OPCODE_ERASE_INDEX           5
+#define SPI_OPCODE_READ_S_INDEX          6
+#define SPI_OPCODE_CHIP_ERASE_INDEX      7
+
+#define SPI_ERASE_SECTOR_SIZE            SIZE_4KB  //This is the chipset requirement
+
+STATIC EFI_PHYSICAL_ADDRESS     mInternalFdAddress;
+EFI_SPI_PROTOCOL                *mSpiProtocol;
+
+/**
+  Writes specified number of bytes from the input buffer to the address
+
+  @param WriteAddress  The flash address to be written.
+  @param NumBytes      The number of bytes.
+  @param Buffer        The data buffer to be written.
+
+  @return The status of flash write.
+**/
+EFI_STATUS
+FlashFdWrite (
+  IN  UINTN                               WriteAddress,
+  IN OUT UINTN                            *NumBytes,
+  IN  UINT8                               *Buffer
+  )
+{
+  EFI_STATUS  Status;
+
+  Status = EFI_SUCCESS;
+
+  Status = mSpiProtocol->Execute (
+                           mSpiProtocol,
+                           SPI_OPCODE_WRITE_INDEX, // OpcodeIndex
+                           0,                      // PrefixOpcodeIndex
+                           TRUE,                   // DataCycle
+                           TRUE,                   // Atomic
+                           TRUE,                   // ShiftOut
+                           WriteAddress,           // Address
+                           (UINT32) (*NumBytes),   // Data Number
+                           Buffer,
+                           EnumSpiRegionBios
+                           );
+  DEBUG((EFI_D_INFO, "FlashFdWrite - 0x%x - %r\n", (UINTN)WriteAddress, Status));
+
+  AsmWbinvd ();
+
+  return Status;
+}
+
+/**
+  Erase a certain block from address LbaWriteAddress
+
+  @param WriteAddress  The flash address to be erased.
+
+  @return The status of flash erase.
+**/
+EFI_STATUS
+FlashFdErase (
+  IN UINTN                                WriteAddress
+  )
+{
+  EFI_STATUS  Status;
+
+  Status = mSpiProtocol->Execute (
+                           mSpiProtocol,
+                           SPI_OPCODE_ERASE_INDEX, // OpcodeIndex
+                           0,                      // PrefixOpcodeIndex
+                           FALSE,                  // DataCycle
+                           TRUE,                   // Atomic
+                           FALSE,                  // ShiftOut
+                           WriteAddress,           // Address
+                           0,                      // Data Number
+                           NULL,
+                           EnumSpiRegionBios       // SPI_REGION_TYPE
+                           );
+  DEBUG((EFI_D_INFO, "FlashFdErase - 0x%x - %r\n", (UINTN)WriteAddress, Status));
+
+  AsmWbinvd ();
+
+  return Status;
+}
+
+/**
+  Perform flash write opreation.
+
+  @param FirmwareType      The type of firmware.
+  @param FlashAddress      The address of flash device to be accessed.
+  @param FlashAddressType  The type of flash device address.
+  @param Buffer            The pointer to the data buffer.
+  @param Length            The length of data buffer in bytes.
+
+  @retval EFI_SUCCESS           The operation returns successfully.
+  @retval EFI_WRITE_PROTECTED   The flash device is read only.
+  @retval EFI_UNSUPPORTED       The flash device access is unsupported.
+  @retval EFI_INVALID_PARAMETER The input parameter is not valid.
+**/
+EFI_STATUS
+EFIAPI
+PerformFlashWrite(
+  IN PLATFORM_FIRMWARE_TYPE       FirmwareType,
+  IN EFI_PHYSICAL_ADDRESS         FlashAddress,
+  IN FLASH_ADDRESS_TYPE           FlashAddressType,
+  IN VOID                         *Buffer,
+  IN UINTN                        Length
+  )
+{
+  EFI_STATUS          Status;
+  UINTN               SectorNum;
+  UINTN               Index;
+  UINTN               NumBytes;
+
+  DEBUG((EFI_D_INFO, "PerformFlashWrite - 0x%x(%x) - 0x%x\n", (UINTN)FlashAddress, (UINTN)FlashAddressType, Length));
+  if (FirmwareType >= PlatformFirmwareTypeMax) {
+    return EFI_UNSUPPORTED;
+  }
+  if (FlashAddressType == FlashAddressTypeAbsoluteAddress) {
+    FlashAddress = FlashAddress - mInternalFdAddress;
+  }
+
+  //
+  // Erase & Write
+  //
+  SectorNum = Length / SPI_ERASE_SECTOR_SIZE;
+  for (Index = 0; Index < SectorNum; Index++){
+    Status = FlashFdErase (
+               (UINTN)FlashAddress + Index * SPI_ERASE_SECTOR_SIZE
+               );
+    if (Status != EFI_SUCCESS){
+      break;
+    }
+    NumBytes = SPI_ERASE_SECTOR_SIZE;
+    Status = FlashFdWrite (
+               (UINTN)FlashAddress + Index * SPI_ERASE_SECTOR_SIZE,
+               &NumBytes,
+               (UINT8 *)Buffer + Index * SPI_ERASE_SECTOR_SIZE
+               );
+    if (Status != EFI_SUCCESS){
+      break;
+    }
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Platform Flash Access Lib Constructor.
+
+  @param  ImageHandle       The firmware allocated handle for the EFI image.
+  @param  SystemTable       A pointer to the EFI System Table.
+
+  @retval EFI_SUCCESS  Constructor returns successfully.
+**/
+EFI_STATUS
+EFIAPI
+PerformFlashAccessLibConstructor (
+  IN EFI_HANDLE                         ImageHandle,
+  IN EFI_SYSTEM_TABLE                   *SystemTable
+  )
+{
+  EFI_STATUS  Status;
+
+  mInternalFdAddress = FixedPcdGet64(PcdFlashAreaBaseAddress);
+  DEBUG((EFI_D_INFO, "PcdFlashAreaBaseAddress - 0x%x\n", mInternalFdAddress));
+
+  Status = gBS->LocateProtocol(&gEfiSpiProtocolGuid, NULL, (VOID **)&mSpiProtocol);
+  ASSERT_EFI_ERROR(Status);
+
+  return EFI_SUCCESS;
+}
diff --git a/QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLibDxe.inf b/QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLibDxe.inf
new file mode 100644
index 0000000..2099bf6
--- /dev/null
+++ b/QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLibDxe.inf
@@ -0,0 +1,52 @@
+## @file
+#  Platform Flash Access library.
+#
+#  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = PlatformFlashAccessLibDxe
+  FILE_GUID                      = 9168384A-5F66-4CF7-AEB6-845BDEBD3012
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = PlatformFlashAccessLib|DXE_DRIVER DXE_RUNTIME_DRIVER
+  CONSTRUCTOR                    = PerformFlashAccessLibConstructor
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64 IPF EBC
+#
+
+[Sources]
+  PlatformFlashAccessLibDxe.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  QuarkSocPkg/QuarkSocPkg.dec
+  QuarkPlatformPkg/QuarkPlatformPkg.dec
+
+[LibraryClasses]
+  BaseMemoryLib
+  PcdLib
+  DebugLib
+  UefiBootServicesTableLib
+
+[Protocols]
+  gEfiSpiProtocolGuid
+
+[FixedPcd]
+  gQuarkPlatformTokenSpaceGuid.PcdFlashAreaBaseAddress
+
+[Depex]
+  gEfiSpiProtocolGuid
diff --git a/QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/SpiFlashDevice.c b/QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/SpiFlashDevice.c
new file mode 100644
index 0000000..e2827b9
--- /dev/null
+++ b/QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/SpiFlashDevice.c
@@ -0,0 +1,336 @@
+/** @file
+  SPI flash device description.
+
+  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+
+**/
+
+#include "SpiFlashDevice.h"
+
+#define FLASH_SIZE  (FixedPcdGet32 (PcdFlashAreaSize))
+
+SPI_INIT_TABLE  mSpiInitTable[] = {
+  //
+  // Macronix 32Mbit part
+  //
+  {
+    SPI_MX25L3205_ID1,
+    SPI_MX25L3205_ID2,
+    SPI_MX25L3205_ID3,
+    {
+      SPI_COMMAND_WRITE_ENABLE,
+      SPI_COMMAND_WRITE_S_EN
+    },
+    {
+      {EnumSpiOpcodeReadNoAddr,  SPI_COMMAND_JEDEC_ID,    EnumSpiCycle33MHz, EnumSpiOperationJedecId},
+      {EnumSpiOpcodeRead,        SPI_COMMAND_READ_ID,     EnumSpiCycle33MHz, EnumSpiOperationOther},
+      {EnumSpiOpcodeWriteNoAddr, SPI_COMMAND_WRITE_S,     EnumSpiCycle33MHz, EnumSpiOperationWriteStatus},
+      {EnumSpiOpcodeWrite,       SPI_COMMAND_WRITE,       EnumSpiCycle33MHz, EnumSpiOperationProgramData_1_Byte},
+      {EnumSpiOpcodeRead,        SPI_COMMAND_READ,        EnumSpiCycle20MHz, EnumSpiOperationReadData},
+      {EnumSpiOpcodeWrite,       SPI_COMMAND_BLOCK_ERASE, EnumSpiCycle33MHz, EnumSpiOperationErase_64K_Byte},
+      {EnumSpiOpcodeReadNoAddr,  SPI_COMMAND_READ_S,      EnumSpiCycle33MHz, EnumSpiOperationReadStatus},
+      {EnumSpiOpcodeWriteNoAddr, SPI_COMMAND_CHIP_ERASE,  EnumSpiCycle33MHz, EnumSpiOperationFullChipErase}
+    },
+    (UINTN)(0x400000 - FLASH_SIZE), // BIOS Start Offset
+    FLASH_SIZE   // BIOS image size in flash
+  },
+  //
+  // Winbond 32Mbit part
+  //
+  {
+    SPI_W25X32_ID1,
+    SF_DEVICE_ID0_W25QXX,
+    SF_DEVICE_ID1_W25Q32,
+    {
+      SPI_COMMAND_WRITE_ENABLE,
+      SPI_COMMAND_WRITE_S_EN
+    },
+    {
+      {EnumSpiOpcodeReadNoAddr,  SPI_COMMAND_JEDEC_ID,    EnumSpiCycle50MHz, EnumSpiOperationJedecId},
+      {EnumSpiOpcodeRead,        SPI_COMMAND_READ_ID,     EnumSpiCycle50MHz, EnumSpiOperationOther},
+      {EnumSpiOpcodeWriteNoAddr, SPI_COMMAND_WRITE_S,     EnumSpiCycle50MHz, EnumSpiOperationWriteStatus},
+      {EnumSpiOpcodeWrite,       SPI_COMMAND_WRITE,       EnumSpiCycle50MHz, EnumSpiOperationProgramData_1_Byte},
+      {EnumSpiOpcodeRead,        SPI_COMMAND_READ,        EnumSpiCycle50MHz, EnumSpiOperationReadData},
+      {EnumSpiOpcodeWrite,       SPI_COMMAND_ERASE,       EnumSpiCycle50MHz, EnumSpiOperationErase_4K_Byte},
+      {EnumSpiOpcodeReadNoAddr,  SPI_COMMAND_READ_S,      EnumSpiCycle50MHz, EnumSpiOperationReadStatus},
+      {EnumSpiOpcodeWriteNoAddr, SPI_COMMAND_CHIP_ERASE,  EnumSpiCycle50MHz, EnumSpiOperationFullChipErase}
+    },
+    (UINTN)(0x400000 - FLASH_SIZE), // BIOS Start Offset
+    FLASH_SIZE   // BIOS image size in flash
+  },
+  //
+  // Winbond 32Mbit part
+  //
+  {
+    SPI_W25X32_ID1,
+    SPI_W25X32_ID2,
+    SPI_W25X32_ID3,
+    {
+      SPI_COMMAND_WRITE_ENABLE,
+      SPI_COMMAND_WRITE_S_EN
+    },
+    {
+      {EnumSpiOpcodeReadNoAddr,  SPI_COMMAND_JEDEC_ID,    EnumSpiCycle33MHz, EnumSpiOperationJedecId},
+      {EnumSpiOpcodeRead,        SPI_COMMAND_READ_ID,     EnumSpiCycle33MHz, EnumSpiOperationOther},
+      {EnumSpiOpcodeWriteNoAddr, SPI_COMMAND_WRITE_S,     EnumSpiCycle33MHz, EnumSpiOperationWriteStatus},
+      {EnumSpiOpcodeWrite,       SPI_COMMAND_WRITE,       EnumSpiCycle33MHz, EnumSpiOperationProgramData_1_Byte},
+      {EnumSpiOpcodeRead,        SPI_COMMAND_READ,        EnumSpiCycle33MHz, EnumSpiOperationReadData},
+      {EnumSpiOpcodeWrite,       SPI_COMMAND_ERASE,       EnumSpiCycle33MHz, EnumSpiOperationErase_4K_Byte},
+      {EnumSpiOpcodeReadNoAddr,  SPI_COMMAND_READ_S,      EnumSpiCycle33MHz, EnumSpiOperationReadStatus},
+      {EnumSpiOpcodeWriteNoAddr, SPI_COMMAND_CHIP_ERASE,  EnumSpiCycle33MHz, EnumSpiOperationFullChipErase}
+    },
+    (UINTN)(0x400000 - FLASH_SIZE), // BIOS Start Offset
+    FLASH_SIZE   // BIOS image size in flash
+  },
+  //
+  // Atmel 32Mbit part
+  //
+  {
+    SPI_AT26DF321_ID1,
+    SPI_AT26DF321_ID2,  // issue: byte 2 identifies family/density for Atmel
+    SPI_AT26DF321_ID3,
+    {
+      SPI_COMMAND_WRITE_ENABLE,
+      SPI_COMMAND_WRITE_S_EN
+    },
+    {
+      {EnumSpiOpcodeReadNoAddr,  SPI_COMMAND_JEDEC_ID,    EnumSpiCycle33MHz, EnumSpiOperationJedecId},
+      {EnumSpiOpcodeRead,        SPI_COMMAND_READ_ID,     EnumSpiCycle33MHz, EnumSpiOperationOther},
+      {EnumSpiOpcodeWriteNoAddr, SPI_COMMAND_WRITE_S,     EnumSpiCycle33MHz, EnumSpiOperationWriteStatus},
+      {EnumSpiOpcodeWrite,       SPI_COMMAND_WRITE,       EnumSpiCycle33MHz, EnumSpiOperationProgramData_1_Byte},
+      {EnumSpiOpcodeRead,        SPI_COMMAND_READ,        EnumSpiCycle33MHz, EnumSpiOperationReadData},
+      {EnumSpiOpcodeWrite,       SPI_COMMAND_BLOCK_ERASE, EnumSpiCycle33MHz, EnumSpiOperationErase_64K_Byte},
+      {EnumSpiOpcodeReadNoAddr,  SPI_COMMAND_READ_S,      EnumSpiCycle33MHz, EnumSpiOperationReadStatus},
+      {EnumSpiOpcodeWriteNoAddr, SPI_COMMAND_CHIP_ERASE,  EnumSpiCycle33MHz, EnumSpiOperationFullChipErase}
+    },
+    (UINTN)(0x400000 - FLASH_SIZE), // BIOS Start Offset
+    FLASH_SIZE   // BIOS image size in flash
+  },
+
+  //
+  // Intel 32Mbit part bottom boot
+  //
+  {
+    SPI_QH25F320_ID1,
+    SPI_QH25F320_ID2,
+    SPI_QH25F320_ID3,
+    {
+      SPI_COMMAND_WRITE_ENABLE,
+      SPI_COMMAND_WRITE_ENABLE
+    },
+    {
+      {EnumSpiOpcodeReadNoAddr,  SPI_COMMAND_JEDEC_ID,    EnumSpiCycle33MHz, EnumSpiOperationJedecId},
+      {EnumSpiOpcodeRead,        SPI_COMMAND_READ_ID,     EnumSpiCycle33MHz, EnumSpiOperationOther},
+      {EnumSpiOpcodeWriteNoAddr, SPI_COMMAND_WRITE_S,     EnumSpiCycle33MHz, EnumSpiOperationWriteStatus},
+      {EnumSpiOpcodeWrite,       SPI_COMMAND_WRITE,       EnumSpiCycle33MHz, EnumSpiOperationProgramData_1_Byte},
+      {EnumSpiOpcodeRead,        SPI_COMMAND_READ,        EnumSpiCycle33MHz, EnumSpiOperationReadData},
+      {EnumSpiOpcodeWrite,       SPI_COMMAND_BLOCK_ERASE, EnumSpiCycle33MHz, EnumSpiOperationErase_64K_Byte},
+      {EnumSpiOpcodeReadNoAddr,  SPI_COMMAND_READ_S,      EnumSpiCycle33MHz, EnumSpiOperationReadStatus},
+      {EnumSpiOpcodeWriteNoAddr, SPI_COMMAND_CHIP_ERASE,  EnumSpiCycle33MHz, EnumSpiOperationFullChipErase}
+    },
+    0,           // BIOS Start Offset
+    FLASH_SIZE   // BIOS image size in flash
+  },
+  //
+  // SST 64Mbit part
+  //
+  {
+    SPI_SST25VF080B_ID1,      // VendorId
+    SF_DEVICE_ID0_25VF064C,   // DeviceId 0
+    SF_DEVICE_ID1_25VF064C,   // DeviceId 1
+    {
+      SPI_COMMAND_WRITE_ENABLE,
+      SPI_COMMAND_WRITE_S_EN
+    },
+    {
+      {EnumSpiOpcodeReadNoAddr,  SPI_COMMAND_JEDEC_ID,    EnumSpiCycle50MHz, EnumSpiOperationJedecId},
+      {EnumSpiOpcodeRead,        SPI_COMMAND_READ_ID,     EnumSpiCycle50MHz, EnumSpiOperationOther},
+      {EnumSpiOpcodeWriteNoAddr, SPI_COMMAND_WRITE_S,     EnumSpiCycle50MHz, EnumSpiOperationWriteStatus},
+      {EnumSpiOpcodeWrite,       SPI_COMMAND_WRITE,       EnumSpiCycle50MHz, EnumSpiOperationProgramData_1_Byte},
+      {EnumSpiOpcodeRead,        SPI_COMMAND_READ,        EnumSpiCycle50MHz, EnumSpiOperationReadData},
+      {EnumSpiOpcodeWrite,       SPI_COMMAND_ERASE,       EnumSpiCycle50MHz, EnumSpiOperationErase_4K_Byte},
+      {EnumSpiOpcodeReadNoAddr,  SPI_COMMAND_READ_S,      EnumSpiCycle50MHz, EnumSpiOperationReadStatus},
+      {EnumSpiOpcodeWriteNoAddr, SPI_COMMAND_CHIP_ERASE,  EnumSpiCycle50MHz, EnumSpiOperationFullChipErase}
+    },
+    0x800000 - FLASH_SIZE,          // BIOS Start Offset
+    FLASH_SIZE   // BIOS image size in flash
+  },
+  //
+  // NUMONYX 64Mbit part
+  //
+  {
+    SF_VENDOR_ID_NUMONYX,     // VendorId
+    SF_DEVICE_ID0_M25PX64,    // DeviceId 0
+    SF_DEVICE_ID1_M25PX64,    // DeviceId 1
+    {
+      SPI_COMMAND_WRITE_ENABLE,
+      SPI_COMMAND_WRITE_S_EN
+    },
+    {
+      {EnumSpiOpcodeReadNoAddr,  SPI_COMMAND_JEDEC_ID,    EnumSpiCycle50MHz, EnumSpiOperationJedecId},
+      {EnumSpiOpcodeRead,        SPI_COMMAND_READ_ID,     EnumSpiCycle50MHz, EnumSpiOperationOther},
+      {EnumSpiOpcodeWriteNoAddr, SPI_COMMAND_WRITE_S,     EnumSpiCycle50MHz, EnumSpiOperationWriteStatus},
+      {EnumSpiOpcodeWrite,       SPI_COMMAND_WRITE,       EnumSpiCycle50MHz, EnumSpiOperationProgramData_1_Byte},
+      {EnumSpiOpcodeRead,        SPI_COMMAND_READ,        EnumSpiCycle50MHz, EnumSpiOperationReadData},
+      {EnumSpiOpcodeWrite,       SPI_COMMAND_ERASE,       EnumSpiCycle50MHz, EnumSpiOperationErase_4K_Byte},
+      {EnumSpiOpcodeReadNoAddr,  SPI_COMMAND_READ_S,      EnumSpiCycle50MHz, EnumSpiOperationReadStatus},
+      {EnumSpiOpcodeWriteNoAddr, SPI_COMMAND_CHIP_ERASE,  EnumSpiCycle50MHz, EnumSpiOperationFullChipErase}
+    },
+    0x800000 - FLASH_SIZE,          // BIOS Start Offset
+    FLASH_SIZE   // BIOS image size in flash
+  },
+  //
+  // Atmel 64Mbit part
+  //
+  {
+    SF_VENDOR_ID_ATMEL,       // VendorId
+    SF_DEVICE_ID0_AT25DF641,  // DeviceId 0
+    SF_DEVICE_ID1_AT25DF641,  // DeviceId 1
+    {
+      SPI_COMMAND_WRITE_ENABLE,
+      SPI_COMMAND_WRITE_S_EN
+    },
+    {
+      {EnumSpiOpcodeReadNoAddr,  SPI_COMMAND_JEDEC_ID,    EnumSpiCycle50MHz, EnumSpiOperationJedecId},
+      {EnumSpiOpcodeRead,        SPI_COMMAND_READ_ID,     EnumSpiCycle50MHz, EnumSpiOperationOther},
+      {EnumSpiOpcodeWriteNoAddr, SPI_COMMAND_WRITE_S,     EnumSpiCycle50MHz, EnumSpiOperationWriteStatus},
+      {EnumSpiOpcodeWrite,       SPI_COMMAND_WRITE,       EnumSpiCycle50MHz, EnumSpiOperationProgramData_1_Byte},
+      {EnumSpiOpcodeRead,        SPI_COMMAND_READ,        EnumSpiCycle50MHz, EnumSpiOperationReadData},
+      {EnumSpiOpcodeWrite,       SPI_COMMAND_ERASE,       EnumSpiCycle50MHz, EnumSpiOperationErase_4K_Byte},
+      {EnumSpiOpcodeReadNoAddr,  SPI_COMMAND_READ_S,      EnumSpiCycle50MHz, EnumSpiOperationReadStatus},
+      {EnumSpiOpcodeWriteNoAddr, SPI_COMMAND_CHIP_ERASE,  EnumSpiCycle50MHz, EnumSpiOperationFullChipErase}
+    },
+    0x800000 - FLASH_SIZE,          // BIOS Start Offset
+    FLASH_SIZE   // BIOS image size in flash
+  },
+
+  //
+  // Spansion 64Mbit part
+  //
+  {
+    SF_VENDOR_ID_SPANSION,       // VendorId
+    SF_DEVICE_ID0_S25FL064K,  // DeviceId 0
+    SF_DEVICE_ID1_S25FL064K,  // DeviceId 1
+    {
+      SPI_COMMAND_WRITE_ENABLE,
+      SPI_COMMAND_WRITE_S_EN
+    },
+    {
+      {EnumSpiOpcodeReadNoAddr,  SPI_COMMAND_JEDEC_ID,    EnumSpiCycle50MHz, EnumSpiOperationJedecId},
+      {EnumSpiOpcodeRead,        SPI_COMMAND_READ_ID,     EnumSpiCycle50MHz, EnumSpiOperationOther},
+      {EnumSpiOpcodeWriteNoAddr, SPI_COMMAND_WRITE_S,     EnumSpiCycle50MHz, EnumSpiOperationWriteStatus},
+      {EnumSpiOpcodeWrite,       SPI_COMMAND_WRITE,       EnumSpiCycle50MHz, EnumSpiOperationProgramData_1_Byte},
+      {EnumSpiOpcodeRead,        SPI_COMMAND_READ,        EnumSpiCycle50MHz, EnumSpiOperationReadData},
+      {EnumSpiOpcodeWrite,       SPI_COMMAND_ERASE,       EnumSpiCycle50MHz, EnumSpiOperationErase_4K_Byte},
+      {EnumSpiOpcodeReadNoAddr,  SPI_COMMAND_READ_S,      EnumSpiCycle50MHz, EnumSpiOperationReadStatus},
+      {EnumSpiOpcodeWriteNoAddr, SPI_COMMAND_CHIP_ERASE,  EnumSpiCycle50MHz, EnumSpiOperationFullChipErase}
+    },
+    0x800000 - FLASH_SIZE,          // BIOS Start Offset
+    FLASH_SIZE   // BIOS image size in flash
+  },
+
+  //
+  // Macronix 64Mbit part bottom boot
+  //
+  {
+    SF_VENDOR_ID_MX,          // VendorId
+    SF_DEVICE_ID0_25L6405D,   // DeviceId 0
+    SF_DEVICE_ID1_25L6405D,   // DeviceId 1
+    {
+      SPI_COMMAND_WRITE_ENABLE,
+      SPI_COMMAND_WRITE_S_EN
+    },
+    {
+      {EnumSpiOpcodeReadNoAddr,  SPI_COMMAND_JEDEC_ID,    EnumSpiCycle50MHz, EnumSpiOperationJedecId},
+      {EnumSpiOpcodeRead,        SPI_COMMAND_READ_ID,     EnumSpiCycle50MHz, EnumSpiOperationOther},
+      {EnumSpiOpcodeWriteNoAddr, SPI_COMMAND_WRITE_S,     EnumSpiCycle50MHz, EnumSpiOperationWriteStatus},
+      {EnumSpiOpcodeWrite,       SPI_COMMAND_WRITE,       EnumSpiCycle50MHz, EnumSpiOperationProgramData_1_Byte},
+      {EnumSpiOpcodeRead,        SPI_COMMAND_READ,        EnumSpiCycle50MHz, EnumSpiOperationReadData},
+      {EnumSpiOpcodeWrite,       SPI_COMMAND_BLOCK_ERASE, EnumSpiCycle50MHz, EnumSpiOperationErase_64K_Byte},
+      {EnumSpiOpcodeReadNoAddr,  SPI_COMMAND_READ_S,      EnumSpiCycle50MHz, EnumSpiOperationReadStatus},
+      {EnumSpiOpcodeWriteNoAddr, SPI_COMMAND_CHIP_ERASE,  EnumSpiCycle50MHz, EnumSpiOperationFullChipErase}
+    },
+    0x800000 - FLASH_SIZE,          // BIOS Start Offset
+    FLASH_SIZE   // BIOS image size in flash
+  },
+  //
+  // Winbond 64Mbit part bottom boot
+  //
+  {
+    SPI_W25X64_ID1,
+    SF_DEVICE_ID0_W25QXX,
+    SF_DEVICE_ID1_W25Q64,
+    {
+      SPI_COMMAND_WRITE_ENABLE,
+      SPI_COMMAND_WRITE_S_EN
+    },
+    {
+      {EnumSpiOpcodeReadNoAddr,  SPI_COMMAND_JEDEC_ID,    EnumSpiCycle50MHz, EnumSpiOperationJedecId},
+      {EnumSpiOpcodeRead,        SPI_COMMAND_READ_ID,     EnumSpiCycle50MHz, EnumSpiOperationOther},
+      {EnumSpiOpcodeWriteNoAddr, SPI_COMMAND_WRITE_S,     EnumSpiCycle50MHz, EnumSpiOperationWriteStatus},
+      {EnumSpiOpcodeWrite,       SPI_COMMAND_WRITE,       EnumSpiCycle50MHz, EnumSpiOperationProgramData_1_Byte},
+      {EnumSpiOpcodeRead,        SPI_COMMAND_READ,        EnumSpiCycle50MHz, EnumSpiOperationReadData},
+      {EnumSpiOpcodeWrite,       SPI_COMMAND_ERASE,       EnumSpiCycle50MHz, EnumSpiOperationErase_4K_Byte},
+      {EnumSpiOpcodeReadNoAddr,  SPI_COMMAND_READ_S,      EnumSpiCycle50MHz, EnumSpiOperationReadStatus},
+      {EnumSpiOpcodeWriteNoAddr, SPI_COMMAND_CHIP_ERASE,  EnumSpiCycle50MHz, EnumSpiOperationFullChipErase}
+    },
+    0x800000 - FLASH_SIZE,          // BIOS Start Offset
+    FLASH_SIZE   // BIOS image size in flash
+  },
+  //
+  // Winbond 64Mbit part bottom boot
+  //
+  {
+    SPI_W25X64_ID1,
+    SPI_W25X64_ID2,
+    SPI_W25X64_ID3,
+    {
+      SPI_COMMAND_WRITE_ENABLE,
+      SPI_COMMAND_WRITE_S_EN
+    },
+    {
+      {EnumSpiOpcodeReadNoAddr,  SPI_COMMAND_JEDEC_ID,    EnumSpiCycle50MHz, EnumSpiOperationJedecId},
+      {EnumSpiOpcodeRead,        SPI_COMMAND_READ_ID,     EnumSpiCycle50MHz, EnumSpiOperationOther},
+      {EnumSpiOpcodeWriteNoAddr, SPI_COMMAND_WRITE_S,     EnumSpiCycle50MHz, EnumSpiOperationWriteStatus},
+      {EnumSpiOpcodeWrite,       SPI_COMMAND_WRITE,       EnumSpiCycle50MHz, EnumSpiOperationProgramData_1_Byte},
+      {EnumSpiOpcodeRead,        SPI_COMMAND_READ,        EnumSpiCycle50MHz, EnumSpiOperationReadData},
+      {EnumSpiOpcodeWrite,       SPI_COMMAND_ERASE,       EnumSpiCycle50MHz, EnumSpiOperationErase_4K_Byte},
+      {EnumSpiOpcodeReadNoAddr,  SPI_COMMAND_READ_S,      EnumSpiCycle50MHz, EnumSpiOperationReadStatus},
+      {EnumSpiOpcodeWriteNoAddr, SPI_COMMAND_CHIP_ERASE,  EnumSpiCycle50MHz, EnumSpiOperationFullChipErase}
+    },
+    0x800000 - FLASH_SIZE,          // BIOS Start Offset
+    FLASH_SIZE   // BIOS image size in flash
+  },
+  //
+  // Intel 64Mbit part bottom boot
+  //
+  {
+    SPI_QH25F640_ID1,
+    SPI_QH25F640_ID2,
+    SPI_QH25F640_ID3,
+    {
+      SPI_COMMAND_WRITE_ENABLE,
+      SPI_COMMAND_WRITE_S_EN
+    },
+    {
+      {EnumSpiOpcodeReadNoAddr,  SPI_COMMAND_JEDEC_ID,    EnumSpiCycle33MHz, EnumSpiOperationJedecId},
+      {EnumSpiOpcodeRead,        SPI_COMMAND_READ_ID,     EnumSpiCycle33MHz, EnumSpiOperationOther},
+      {EnumSpiOpcodeWriteNoAddr, SPI_COMMAND_WRITE_S,     EnumSpiCycle33MHz, EnumSpiOperationWriteStatus},
+      {EnumSpiOpcodeWrite,       SPI_COMMAND_WRITE,       EnumSpiCycle33MHz, EnumSpiOperationProgramData_1_Byte},
+      {EnumSpiOpcodeRead,        SPI_COMMAND_READ,        EnumSpiCycle33MHz, EnumSpiOperationReadData},
+      {EnumSpiOpcodeWrite,       SPI_COMMAND_BLOCK_ERASE, EnumSpiCycle33MHz, EnumSpiOperationErase_64K_Byte},
+      {EnumSpiOpcodeReadNoAddr,  SPI_COMMAND_READ_S,      EnumSpiCycle33MHz, EnumSpiOperationReadStatus},
+      {EnumSpiOpcodeWriteNoAddr, SPI_COMMAND_CHIP_ERASE,  EnumSpiCycle33MHz, EnumSpiOperationFullChipErase}
+    },
+    0x800000 - FLASH_SIZE,          // BIOS Start Offset
+    FLASH_SIZE   // BIOS image size in flash
+  }
+};
diff --git a/QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/SpiFlashDevice.h b/QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/SpiFlashDevice.h
new file mode 100644
index 0000000..298ecfa
--- /dev/null
+++ b/QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/SpiFlashDevice.h
@@ -0,0 +1,186 @@
+/** @file
+  SPI flash device header file.
+
+  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _SPI_FLASH_DEVICE_H_
+#define _SPI_FLASH_DEVICE_H_
+
+#include <PiDxe.h>
+#include <Protocol/Spi.h>
+#include <Protocol/FirmwareVolumeBlock.h>
+
+//
+// Supported SPI Flash Devices
+//
+typedef enum {
+  EnumSpiFlash25L3205D,   // Macronix 32Mbit part
+  EnumSpiFlashW25Q32,     // Winbond 32Mbit part
+  EnumSpiFlashW25X32,     // Winbond 32Mbit part
+  EnumSpiFlashAT25DF321,  // Atmel 32Mbit part
+  EnumSpiFlashQH25F320,   // Intel 32Mbit part
+  EnumSpiFlash25VF064C,   // SST 64Mbit part
+  EnumSpiFlashM25PX64,    // NUMONYX 64Mbit part
+  EnumSpiFlashAT25DF641,  // Atmel 64Mbit part
+  EnumSpiFlashS25FL064K,  // Spansion 64Mbit part
+  EnumSpiFlash25L6405D,   // Macronix 64Mbit part
+  EnumSpiFlashW25Q64,     // Winbond 64Mbit part
+  EnumSpiFlashW25X64,     // Winbond 64Mbit part
+  EnumSpiFlashQH25F640,   // Intel 64Mbit part
+  EnumSpiFlashMax
+} SPI_FLASH_TYPES_SUPPORTED;
+
+//
+// Flash Device commands
+//
+// If a supported device uses a command different from the list below, a device specific command
+// will be defined just below it's JEDEC id section.
+//
+#define SPI_COMMAND_WRITE                 0x02
+#define SPI_COMMAND_WRITE_AAI             0xAD
+#define SPI_COMMAND_READ                  0x03
+#define SPI_COMMAND_ERASE                 0x20
+#define SPI_COMMAND_WRITE_DISABLE         0x04
+#define SPI_COMMAND_READ_S                0x05
+#define SPI_COMMAND_WRITE_ENABLE          0x06
+#define SPI_COMMAND_READ_ID               0xAB
+#define SPI_COMMAND_JEDEC_ID              0x9F
+#define SPI_COMMAND_WRITE_S_EN            0x50
+#define SPI_COMMAND_WRITE_S               0x01
+#define SPI_COMMAND_CHIP_ERASE            0xC7
+#define SPI_COMMAND_BLOCK_ERASE           0xD8
+
+//
+// Flash JEDEC device ids
+//
+// SST 8Mbit part
+//
+#define SPI_SST25VF080B_ID1               0xBF
+#define SPI_SST25VF080B_ID2               0x25
+#define SPI_SST25VF080B_ID3               0x8E
+//
+// SST 16Mbit part
+//
+#define SPI_SST25VF016B_ID1               0xBF
+#define SPI_SST25VF016B_ID2               0x25
+#define SPI_SST25V016BF_ID3               0x41
+//
+// Macronix 32Mbit part
+//
+// MX25 part does not support WRITE_AAI comand (0xAD)
+//
+#define SPI_MX25L3205_ID1                 0xC2
+#define SPI_MX25L3205_ID2                 0x20
+#define SPI_MX25L3205_ID3                 0x16
+//
+// Intel 32Mbit part bottom boot
+//
+#define SPI_QH25F320_ID1                  0x89
+#define SPI_QH25F320_ID2                  0x89
+#define SPI_QH25F320_ID3                  0x12  // 32Mbit bottom boot
+//
+// Intel 64Mbit part bottom boot
+//
+#define SPI_QH25F640_ID1                  0x89
+#define SPI_QH25F640_ID2                  0x89
+#define SPI_QH25F640_ID3                  0x13  // 64Mbit bottom boot
+//
+// QH part does not support command 0x20 for erase; only 0xD8 (sector erase)
+// QH part has 0x40 command for erase of parameter block (8 x 8K blocks at bottom of part)
+// 0x40 command ignored if address outside of parameter block range
+//
+#define SPI_QH25F320_COMMAND_PBLOCK_ERASE 0x40
+//
+// Winbond 32Mbit part
+//
+#define SPI_W25X32_ID1                    0xEF
+#define SPI_W25X32_ID2                    0x30  // Memory Type
+#define SPI_W25X32_ID3                    0x16  // Capacity
+#define SF_DEVICE_ID1_W25Q32              0x16
+
+//
+// Winbond 64Mbit part
+//
+#define SPI_W25X64_ID1                    0xEF
+#define SPI_W25X64_ID2                    0x30  // Memory Type
+#define SPI_W25X64_ID3                    0x17  // Capacity
+#define SF_DEVICE_ID0_W25QXX              0x40
+#define SF_DEVICE_ID1_W25Q64              0x17
+//
+// Winbond 128Mbit part
+//
+#define SF_DEVICE_ID0_W25Q128             0x40
+#define SF_DEVICE_ID1_W25Q128             0x18
+
+//
+// Atmel 32Mbit part
+//
+#define SPI_AT26DF321_ID1                 0x1F
+#define SPI_AT26DF321_ID2                 0x47  // [7:5]=Family, [4:0]=Density
+#define SPI_AT26DF321_ID3                 0x00
+
+#define SF_VENDOR_ID_ATMEL                0x1F
+#define SF_DEVICE_ID0_AT25DF641           0x48
+#define SF_DEVICE_ID1_AT25DF641           0x00
+
+//
+// SST 8Mbit part
+//
+#define SPI_SST25VF080B_ID1               0xBF
+#define SPI_SST25VF080B_ID2               0x25
+#define SPI_SST25VF080B_ID3               0x8E
+#define SF_DEVICE_ID0_25VF064C            0x25
+#define SF_DEVICE_ID1_25VF064C            0x4B
+
+//
+// SST 16Mbit part
+//
+#define SPI_SST25VF016B_ID1               0xBF
+#define SPI_SST25VF016B_ID2               0x25
+#define SPI_SST25V016BF_ID3               0x41
+
+//
+// Winbond 32Mbit part
+//
+#define SPI_W25X32_ID1                    0xEF
+#define SPI_W25X32_ID2                    0x30  // Memory Type
+#define SPI_W25X32_ID3                    0x16  // Capacity
+
+#define  SF_VENDOR_ID_MX             0xC2
+#define  SF_DEVICE_ID0_25L6405D      0x20
+#define  SF_DEVICE_ID1_25L6405D      0x17
+
+#define  SF_VENDOR_ID_NUMONYX        0x20
+#define  SF_DEVICE_ID0_M25PX64       0x71
+#define  SF_DEVICE_ID1_M25PX64       0x17
+
+//
+// Spansion 64Mbit part
+//
+#define SF_VENDOR_ID_SPANSION             0xEF
+#define SF_DEVICE_ID0_S25FL064K           0x40
+#define SF_DEVICE_ID1_S25FL064K           0x00
+
+//
+// index for prefix opcodes
+//
+#define SPI_WREN_INDEX                    0   // Prefix Opcode 0: SPI_COMMAND_WRITE_ENABLE
+#define SPI_EWSR_INDEX                    1   // Prefix Opcode 1: SPI_COMMAND_WRITE_S_EN
+#define BIOS_CTRL                         0xDC
+
+#define PFAB_CARD_DEVICE_ID               0x5150
+#define PFAB_CARD_VENDOR_ID               0x8086
+#define PFAB_CARD_SETUP_REGISTER          0x40
+#define PFAB_CARD_SETUP_BYTE              0x0d
+
+
+#endif
-- 
2.7.4.windows.1



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

* [PATCH 32/45] QuarkPlatformPkg/SystemBiosDescriptor: Add Descriptor for capsule update.
  2016-09-21  6:44 [PATCH 00/45] Add capsule update and recovery sample Jiewen Yao
                   ` (30 preceding siblings ...)
  2016-09-21  6:45 ` [PATCH 31/45] QuarkPlatformPkg/PlatformFlashAccessLib: Add instance for capsule update Jiewen Yao
@ 2016-09-21  6:45 ` Jiewen Yao
  2016-09-21  6:45 ` [PATCH 33/45] QuarkPlatformPkg/SystemBiosUpdateConfig: Add capsule config file Jiewen Yao
                   ` (16 subsequent siblings)
  48 siblings, 0 replies; 83+ messages in thread
From: Jiewen Yao @ 2016-09-21  6:45 UTC (permalink / raw)
  To: edk2-devel
  Cc: Michael D Kinney, Kelly Steele, Feng Tian, Star Zeng, Liming Gao,
	Chao Zhang

Add SystemBiosDescriptor for capsule update.
The PEIM extracts SystemBiosDescriptor info from FFS and reports it via PCD.

Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Kelly Steele <kelly.steele@intel.com>
Cc: Feng Tian <feng.tian@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Chao Zhang <chao.b.zhang@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
---
 QuarkPlatformPkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptor.aslc | 88 ++++++++++++++++++++
 QuarkPlatformPkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptor.inf  | 45 ++++++++++
 QuarkPlatformPkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptorPei.c | 66 +++++++++++++++
 3 files changed, 199 insertions(+)

diff --git a/QuarkPlatformPkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptor.aslc b/QuarkPlatformPkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptor.aslc
new file mode 100644
index 0000000..e84b783
--- /dev/null
+++ b/QuarkPlatformPkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptor.aslc
@@ -0,0 +1,88 @@
+/** @file
+  System BIOS descriptor.
+
+  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <PiPei.h>
+#include <Protocol/FirmwareManagement.h>
+#include <Guid/EdkiiSystemFmpCapsule.h>
+
+#define PACKAGE_VERSION                     0xFFFFFFFF
+#define PACKAGE_VERSION_STRING              L"Unknown"
+
+#define CURRENT_FIRMWARE_VERSION            0x00000002
+#define CURRENT_FIRMWARE_VERSION_STRING     L"0x00000002"
+#define LOWEST_SUPPORTED_FIRMWARE_VERSION   0x00000001
+
+#define IMAGE_ID                            SIGNATURE_64('Q', 'U', 'A', 'R', 'K', '_', 'F', 'd')
+#define IMAGE_ID_STRING                     L"QuarkPlatformFd"
+
+#define IMAGE_TYPE_ID_GUID                  { 0x62af20c0, 0x7016, 0x424a, { 0x9b, 0xf8, 0x9c, 0xcc, 0x86, 0x58, 0x40, 0x90 } }
+
+typedef struct {
+  EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR  Descriptor;
+  // real string data
+  CHAR16                                  ImageIdNameStr[16];
+  CHAR16                                  VersionNameStr[16];
+  CHAR16                                  PackageVersionNameStr[16];
+} IMAGE_DESCRIPTOR;
+
+IMAGE_DESCRIPTOR mImageDescriptor =
+{
+  {
+    EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR_SIGNATURE,
+    sizeof(EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR),
+    sizeof(IMAGE_DESCRIPTOR),
+    PACKAGE_VERSION,                                       // PackageVersion
+    OFFSET_OF (IMAGE_DESCRIPTOR, PackageVersionNameStr),   // PackageVersionName
+    1,                                                     // ImageIndex;
+    {0x0},                                                 // Reserved
+    IMAGE_TYPE_ID_GUID,                                    // ImageTypeId;
+    IMAGE_ID,                                              // ImageId;
+    OFFSET_OF (IMAGE_DESCRIPTOR, ImageIdNameStr),          // ImageIdName;
+    CURRENT_FIRMWARE_VERSION,                              // Version;
+    OFFSET_OF (IMAGE_DESCRIPTOR, VersionNameStr),          // VersionName;
+    {0x0},                                                 // Reserved2
+    FixedPcdGet32(PcdFlashAreaSize),                       // Size;
+    IMAGE_ATTRIBUTE_IMAGE_UPDATABLE |
+      IMAGE_ATTRIBUTE_RESET_REQUIRED |
+      IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED |
+      IMAGE_ATTRIBUTE_IN_USE,                              // AttributesSupported;
+    IMAGE_ATTRIBUTE_IMAGE_UPDATABLE |
+      IMAGE_ATTRIBUTE_RESET_REQUIRED |
+      IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED |
+      IMAGE_ATTRIBUTE_IN_USE,                              // AttributesSetting;
+    0x0,                                                   // Compatibilities;
+    LOWEST_SUPPORTED_FIRMWARE_VERSION,                     // LowestSupportedImageVersion;
+    0x00000000,                                            // LastAttemptVersion;
+    0,                                                     // LastAttemptStatus;
+    {0x0},                                                 // Reserved3
+    0,                                                     // HardwareInstance;
+  },
+  // real string data
+  {IMAGE_ID_STRING},
+  {CURRENT_FIRMWARE_VERSION_STRING},
+  {PACKAGE_VERSION_STRING},
+};
+
+
+VOID*
+ReferenceAcpiTable (
+  VOID
+  )
+{
+  //
+  // Reference the table being generated to prevent the optimizer from
+  // removing the data structure from the executable
+  //
+  return (VOID*)&mImageDescriptor;
+}
diff --git a/QuarkPlatformPkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptor.inf b/QuarkPlatformPkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptor.inf
new file mode 100644
index 0000000..2d6840c
--- /dev/null
+++ b/QuarkPlatformPkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptor.inf
@@ -0,0 +1,45 @@
+## @file
+#  System BIOS descriptor.
+#
+#  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = SystemBiosDescriptor
+  FILE_GUID                      = 90B2B846-CA6D-4D6E-A8D3-C140A8E110AC
+  MODULE_TYPE                    = PEIM
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = SystemBiosDescriptorPeimEntry
+
+[Sources]
+  SystemBiosDescriptorPei.c
+  SystemBiosDescriptor.aslc
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  QuarkPlatformPkg/QuarkPlatformPkg.dec
+
+[LibraryClasses]
+  PcdLib
+  PeiServicesLib
+  DebugLib
+  PeimEntryPoint
+
+[FixedPcd]
+  gQuarkPlatformTokenSpaceGuid.PcdFlashAreaSize
+
+[Pcd]
+  gEfiMdeModulePkgTokenSpaceGuid.PcdEdkiiSystemFirmwareImageDescriptor
+
+[Depex]
+  TRUE
diff --git a/QuarkPlatformPkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptorPei.c b/QuarkPlatformPkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptorPei.c
new file mode 100644
index 0000000..6272138
--- /dev/null
+++ b/QuarkPlatformPkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptorPei.c
@@ -0,0 +1,66 @@
+/** @file
+  System BIOS descriptor producer.
+
+  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <PiPei.h>
+#include <Library/PcdLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/DebugLib.h>
+#include <Protocol/FirmwareManagement.h>
+#include <Guid/EdkiiSystemFmpCapsule.h>
+
+/**
+  Entrypoint for SystemBiosDescriptor PEIM.
+
+  @param  FileHandle  Handle of the file being invoked.
+  @param  PeiServices Describes the list of possible PEI Services.
+
+  @retval EFI_SUCCESS            PPI successfully installed.
+**/
+EFI_STATUS
+EFIAPI
+SystemBiosDescriptorPeimEntry(
+  IN EFI_PEI_FILE_HANDLE     FileHandle,
+  IN CONST EFI_PEI_SERVICES  **PeiServices
+  )
+{
+  EFI_STATUS                              Status;
+  EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR  *Descriptor;
+  UINTN                                   Size;
+  UINTN                                   Index;
+  UINT32                                  AuthenticationStatus;
+
+  //
+  // Search RAW section.
+  //
+  Index = 0;
+  while (TRUE) {
+    Status = PeiServicesFfsFindSectionData3(EFI_SECTION_RAW, Index, FileHandle, &Descriptor, &AuthenticationStatus);
+    if (EFI_ERROR(Status)) {
+      // Should not happen, must something wrong in FDF.
+      ASSERT(FALSE);
+      return EFI_NOT_FOUND;
+    }
+    if (Descriptor->Signature == EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR_SIGNATURE) {
+      break;
+    }
+    Index++;
+  }
+
+  DEBUG((EFI_D_INFO, "EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR size - 0x%x\n", Descriptor->Length));
+
+  Size = Descriptor->Length;
+  PcdSetPtrS (PcdEdkiiSystemFirmwareImageDescriptor, &Size, Descriptor);
+
+  return EFI_SUCCESS;
+}
-- 
2.7.4.windows.1



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

* [PATCH 33/45] QuarkPlatformPkg/SystemBiosUpdateConfig: Add capsule config file.
  2016-09-21  6:44 [PATCH 00/45] Add capsule update and recovery sample Jiewen Yao
                   ` (31 preceding siblings ...)
  2016-09-21  6:45 ` [PATCH 32/45] QuarkPlatformPkg/SystemBiosDescriptor: Add Descriptor " Jiewen Yao
@ 2016-09-21  6:45 ` Jiewen Yao
  2016-09-21  6:45 ` [PATCH 34/45] QuarkPlatformPkg/PlatformInit: Remove recovery PPI installation Jiewen Yao
                   ` (15 subsequent siblings)
  48 siblings, 0 replies; 83+ messages in thread
From: Jiewen Yao @ 2016-09-21  6:45 UTC (permalink / raw)
  To: edk2-devel
  Cc: Michael D Kinney, Kelly Steele, Feng Tian, Star Zeng, Liming Gao,
	Chao Zhang

Add SystemBiosUpdateConfig as capsule configuration file.

Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Kelly Steele <kelly.steele@intel.com>
Cc: Feng Tian <feng.tian@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Chao Zhang <chao.b.zhang@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
---
 QuarkPlatformPkg/Feature/Capsule/SystemBiosUpdateConfig/SystemBiosUpdateConfig.ini | 62 ++++++++++++++++++++
 1 file changed, 62 insertions(+)

diff --git a/QuarkPlatformPkg/Feature/Capsule/SystemBiosUpdateConfig/SystemBiosUpdateConfig.ini b/QuarkPlatformPkg/Feature/Capsule/SystemBiosUpdateConfig/SystemBiosUpdateConfig.ini
new file mode 100644
index 0000000..ec06934
--- /dev/null
+++ b/QuarkPlatformPkg/Feature/Capsule/SystemBiosUpdateConfig/SystemBiosUpdateConfig.ini
@@ -0,0 +1,62 @@
+## @file
+#
+#  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Head]
+NumOfUpdate = 4
+NumOfRecovery = 1
+Update0 = QuarkFvMain
+Update1 = QuarkFvBinary
+Update2 = QuarkFvRecovery
+Update3 = QuarkFvNvRam
+Recovery0 = QuarkFvMain
+
+[QuarkFvPayload]
+FirmwareType = 0            # BIOS
+AddressType = 0             # 0 - relative address, 1 - absolute address.
+BaseAddress = 0x00400000    # Base address offset on flash
+Length      = 0x00100000    # Length
+ImageOffset = 0x00400000    # Image offset of this BIOS update image
+FileGuid    = AF9C9EB2-12AD-4D3E-A4D4-96F6C9966215
+
+[QuarkFvMain]
+FirmwareType = 0            # BIOS
+AddressType = 0             # 0 - relative address, 1 - absolute address.
+BaseAddress = 0x00500000    # Base address offset on flash
+Length      = 0x001E0000    # Length
+ImageOffset = 0x00500000    # Image offset of this BIOS update image
+FileGuid    = AF9C9EB2-12AD-4D3E-A4D4-96F6C9966215
+
+[QuarkFvNvRam]
+FirmwareType = 1            # NvRam
+AddressType = 0             # 0 - relative address, 1 - absolute address.
+BaseAddress = 0x006E0000    # Base address offset on flash
+Length      = 0x00020000    # Length
+ImageOffset = 0x006E0000    # Image offset of this BIOS update image
+FileGuid    = AF9C9EB2-12AD-4D3E-A4D4-96F6C9966215
+
+[QuarkFvBinary]
+FirmwareType = 0            # BIOS
+AddressType = 0             # 0 - relative address, 1 - absolute address.
+BaseAddress = 0x00700000    # Base address offset on flash
+Length      = 0x00010000    # Length
+ImageOffset = 0x00700000    # Image offset of this BIOS update image
+FileGuid    = AF9C9EB2-12AD-4D3E-A4D4-96F6C9966215
+
+[QuarkFvRecovery]
+FirmwareType = 0            # BIOS
+AddressType = 0             # 0 - relative address, 1 - absolute address.
+BaseAddress = 0x00710000    # Base address offset on flash
+Length      = 0x000F0000    # Length
+ImageOffset = 0x00710000    # Image offset of this BIOS update image
+FileGuid    = AF9C9EB2-12AD-4D3E-A4D4-96F6C9966215
+
-- 
2.7.4.windows.1



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

* [PATCH 34/45] QuarkPlatformPkg/PlatformInit: Remove recovery PPI installation.
  2016-09-21  6:44 [PATCH 00/45] Add capsule update and recovery sample Jiewen Yao
                   ` (32 preceding siblings ...)
  2016-09-21  6:45 ` [PATCH 33/45] QuarkPlatformPkg/SystemBiosUpdateConfig: Add capsule config file Jiewen Yao
@ 2016-09-21  6:45 ` Jiewen Yao
  2016-09-21  6:45 ` [PATCH 35/45] QuarkPlatformPkg/PlatformBootManager: Add capsule/recovery handling Jiewen Yao
                   ` (14 subsequent siblings)
  48 siblings, 0 replies; 83+ messages in thread
From: Jiewen Yao @ 2016-09-21  6:45 UTC (permalink / raw)
  To: edk2-devel
  Cc: Michael D Kinney, Kelly Steele, Feng Tian, Star Zeng, Liming Gao,
	Chao Zhang

The QuarkPlatform will use MdeModulePkg/RecoveryModuleLoadPei for recovery.
There is no need to produce recovery PPI in platform module.

Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Kelly Steele <kelly.steele@intel.com>
Cc: Feng Tian <feng.tian@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Chao Zhang <chao.b.zhang@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
---
 QuarkPlatformPkg/Platform/Pei/PlatformInit/MemoryCallback.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/QuarkPlatformPkg/Platform/Pei/PlatformInit/MemoryCallback.c b/QuarkPlatformPkg/Platform/Pei/PlatformInit/MemoryCallback.c
index d5fb941..f9b769d 100644
--- a/QuarkPlatformPkg/Platform/Pei/PlatformInit/MemoryCallback.c
+++ b/QuarkPlatformPkg/Platform/Pei/PlatformInit/MemoryCallback.c
@@ -222,8 +222,7 @@ MemoryDiscoveredPpiNotifyCallback (
   QNCPortWrite (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC, RegData32);
 
   if (BootMode == BOOT_IN_RECOVERY_MODE) {
-    Status = PeimInitializeRecovery (PeiServices);
-    ASSERT_EFI_ERROR (Status);
+    // Do nothing here. A generic RecoveryModule will handle it.
   } else if (BootMode == BOOT_ON_S3_RESUME) {
     return EFI_SUCCESS;
   } else {
-- 
2.7.4.windows.1



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

* [PATCH 35/45] QuarkPlatformPkg/PlatformBootManager: Add capsule/recovery handling.
  2016-09-21  6:44 [PATCH 00/45] Add capsule update and recovery sample Jiewen Yao
                   ` (33 preceding siblings ...)
  2016-09-21  6:45 ` [PATCH 34/45] QuarkPlatformPkg/PlatformInit: Remove recovery PPI installation Jiewen Yao
@ 2016-09-21  6:45 ` Jiewen Yao
  2016-09-21  6:45 ` [PATCH 36/45] QuarkPlatformPkg/dsc/fdf: Add capsule/recovery support Jiewen Yao
                   ` (13 subsequent siblings)
  48 siblings, 0 replies; 83+ messages in thread
From: Jiewen Yao @ 2016-09-21  6:45 UTC (permalink / raw)
  To: edk2-devel
  Cc: Michael D Kinney, Kelly Steele, Feng Tian, Star Zeng, Liming Gao,
	Chao Zhang

Add capsule and recovery boot path handling in platform BDS.

Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Kelly Steele <kelly.steele@intel.com>
Cc: Feng Tian <feng.tian@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Chao Zhang <chao.b.zhang@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
---
 QuarkPlatformPkg/Library/PlatformBootManagerLib/PlatformBootManager.c      | 95 +++++++++++++++++++-
 QuarkPlatformPkg/Library/PlatformBootManagerLib/PlatformBootManager.h      |  8 +-
 QuarkPlatformPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf |  8 +-
 3 files changed, 106 insertions(+), 5 deletions(-)

diff --git a/QuarkPlatformPkg/Library/PlatformBootManagerLib/PlatformBootManager.c b/QuarkPlatformPkg/Library/PlatformBootManagerLib/PlatformBootManager.c
index 19ff3d0..6a295ed 100644
--- a/QuarkPlatformPkg/Library/PlatformBootManagerLib/PlatformBootManager.c
+++ b/QuarkPlatformPkg/Library/PlatformBootManagerLib/PlatformBootManager.c
@@ -2,7 +2,7 @@
 This file include all platform action which can be customized
 by IBV/OEM.
 
-Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>
 This program and the accompanying materials
 are licensed and made available under the terms and conditions of the BSD License
 which accompanies this distribution.  The full text of the license may be found at
@@ -205,6 +205,8 @@ PlatformBootManagerBeforeConsole (
   EFI_INPUT_KEY                 Enter;
   EFI_INPUT_KEY                 F2;
   EFI_BOOT_MANAGER_LOAD_OPTION  BootOption;
+  ESRT_MANAGEMENT_PROTOCOL      *EsrtManagement;
+  EFI_BOOT_MODE                 BootMode;
   EFI_ACPI_S3_SAVE_PROTOCOL     *AcpiS3Save;
   EFI_HANDLE                    Handle;
   EFI_EVENT                     EndOfDxeEvent;
@@ -246,6 +248,40 @@ PlatformBootManagerBeforeConsole (
   //
   PlatformRegisterFvBootOption (&mUefiShellFileGuid, L"UEFI Shell", LOAD_OPTION_ACTIVE);
 
+  Status = gBS->LocateProtocol(&gEsrtManagementProtocolGuid, NULL, (VOID **)&EsrtManagement);
+  if (EFI_ERROR(Status)) {
+    EsrtManagement = NULL;
+  }
+
+  BootMode = GetBootModeHob();
+  switch (BootMode) {
+  case BOOT_ON_FLASH_UPDATE:
+    DEBUG((EFI_D_INFO, "ProcessCapsules Before EndOfDxe ......\n"));
+    Status = ProcessCapsules ();
+    DEBUG((EFI_D_INFO, "ProcessCapsules %r\n", Status));
+    break;
+  case BOOT_IN_RECOVERY_MODE:
+    break;
+  case BOOT_ASSUMING_NO_CONFIGURATION_CHANGES:
+  case BOOT_WITH_MINIMAL_CONFIGURATION:
+  case BOOT_ON_S4_RESUME:
+    if (EsrtManagement != NULL) {
+      //
+      // Lock ESRT cache repository before EndofDxe if ESRT sync is not needed
+      //
+      EsrtManagement->LockEsrtRepository();
+    }
+    break;
+  default:
+    //
+    // Require to sync ESRT from FMP in a new boot
+    //
+    if (EsrtManagement != NULL) {
+      EsrtManagement->SyncEsrtFmp();
+    }
+    break;
+  }
+
   //
   // Prepare for S3
   //
@@ -303,7 +339,62 @@ PlatformBootManagerAfterConsole (
   VOID
   )
 {
-  EFI_STATUS  Status;
+  EFI_STATUS                     Status;
+  EFI_BOOT_MODE                  BootMode;
+  ESRT_MANAGEMENT_PROTOCOL       *EsrtManagement;
+
+  Status = gBS->LocateProtocol(&gEsrtManagementProtocolGuid, NULL, (VOID **)&EsrtManagement);
+  if (EFI_ERROR(Status)) {
+    EsrtManagement = NULL;
+  }
+
+  BootMode = GetBootModeHob();
+  switch (BootMode) {
+  case BOOT_ON_FLASH_UPDATE:
+    DEBUG((EFI_D_INFO, "Capsule Mode detected\n"));
+    if (FeaturePcdGet(PcdSupportUpdateCapsuleReset)) {
+      EfiBootManagerConnectAll ();
+      EfiBootManagerRefreshAllBootOption ();
+
+      //
+      // Always sync ESRT Cache from FMP Instances after connect all and before capsule process
+      //
+      if (EsrtManagement != NULL) {
+        EsrtManagement->SyncEsrtFmp();
+      }
+
+      DEBUG((EFI_D_INFO, "ProcessCapsules After ConnectAll ......\n"));
+      Status = ProcessCapsules();
+      DEBUG((EFI_D_INFO, "ProcessCapsules %r\n", Status));
+    }
+    break;
+
+  case BOOT_IN_RECOVERY_MODE:
+    DEBUG((EFI_D_INFO, "Recovery Mode detected\n"));
+    // Passthrough
+
+  case BOOT_ASSUMING_NO_CONFIGURATION_CHANGES:
+  case BOOT_WITH_MINIMAL_CONFIGURATION:
+  case BOOT_WITH_FULL_CONFIGURATION:
+  case BOOT_WITH_FULL_CONFIGURATION_PLUS_DIAGNOSTICS:
+  case BOOT_WITH_DEFAULT_SETTINGS:
+  default:
+    EfiBootManagerConnectAll ();
+    EfiBootManagerRefreshAllBootOption ();
+
+    //
+    // Sync ESRT Cache from FMP Instance on demand after Connect All
+    //
+    if ((BootMode != BOOT_ASSUMING_NO_CONFIGURATION_CHANGES) &&
+        (BootMode != BOOT_WITH_MINIMAL_CONFIGURATION) &&
+        (BootMode != BOOT_ON_S4_RESUME)) {
+      if (EsrtManagement != NULL) {
+        EsrtManagement->SyncEsrtFmp();
+      }
+    }
+
+    break;
+  }
 
   Print (
     L"\n"
diff --git a/QuarkPlatformPkg/Library/PlatformBootManagerLib/PlatformBootManager.h b/QuarkPlatformPkg/Library/PlatformBootManagerLib/PlatformBootManager.h
index 7413883..683249b 100644
--- a/QuarkPlatformPkg/Library/PlatformBootManagerLib/PlatformBootManager.h
+++ b/QuarkPlatformPkg/Library/PlatformBootManagerLib/PlatformBootManager.h
@@ -1,7 +1,7 @@
 /** @file
 Head file for BDS Platform specific code
 
-Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>
 This program and the accompanying materials
 are licensed and made available under the terms and conditions of the BSD License
 which accompanies this distribution.  The full text of the license may be found at
@@ -21,6 +21,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include <Protocol/FirmwareVolume2.h>
 #include <Protocol/AcpiS3Save.h>
 #include <Protocol/DxeSmmReadyToLock.h>
+#include <Protocol/EsrtManagement.h>
 #include <Guid/DebugAgentGuid.h>
 #include <Guid/EventGroup.h>
 #include <Guid/PcAnsi.h>
@@ -32,9 +33,12 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include <Library/DevicePathLib.h>
 #include <Library/MemoryAllocationLib.h>
 #include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
 #include <Library/UefiLib.h>
 #include <Library/UefiBootManagerLib.h>
-
+#include <Library/PrintLib.h>
+#include <Library/HobLib.h>
+#include <Library/CapsuleLib.h>
 
 typedef struct {
   EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
diff --git a/QuarkPlatformPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf b/QuarkPlatformPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf
index d59f14a..5526562 100644
--- a/QuarkPlatformPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf
+++ b/QuarkPlatformPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf
@@ -1,7 +1,7 @@
 ## @file
 #  Include all platform action which can be customized by IBV/OEM.
 #
-#  Copyright (c) 2012 - 2015, Intel Corporation. All rights reserved.<BR>
+#  Copyright (c) 2012 - 2016, Intel Corporation. All rights reserved.<BR>
 #  This program and the accompanying materials
 #  are licensed and made available under the terms and conditions of the BSD License
 #  which accompanies this distribution.  The full text of the license may be found at
@@ -49,11 +49,15 @@
   UefiBootServicesTableLib
   UefiLib
   UefiBootManagerLib
+  PrintLib
+  HobLib
+  CapsuleLib
 
 [Protocols]
   gEfiFirmwareVolume2ProtocolGuid
   gEfiAcpiS3SaveProtocolGuid
   gEfiDxeSmmReadyToLockProtocolGuid
+  gEsrtManagementProtocolGuid
 
 [Guids]
   gEfiPcAnsiGuid
@@ -70,3 +74,5 @@
   gEfiMdePkgTokenSpaceGuid.PcdUartDefaultStopBits
   gEfiMdePkgTokenSpaceGuid.PcdDefaultTerminalType
   gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdBootState
+  gEfiMdeModulePkgTokenSpaceGuid.PcdSupportUpdateCapsuleReset
+
-- 
2.7.4.windows.1



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

* [PATCH 36/45] QuarkPlatformPkg/dsc/fdf: Add capsule/recovery support.
  2016-09-21  6:44 [PATCH 00/45] Add capsule update and recovery sample Jiewen Yao
                   ` (34 preceding siblings ...)
  2016-09-21  6:45 ` [PATCH 35/45] QuarkPlatformPkg/PlatformBootManager: Add capsule/recovery handling Jiewen Yao
@ 2016-09-21  6:45 ` Jiewen Yao
  2016-09-21  6:45 ` [PATCH 37/45] QuarkPlatformPkg/dsc/fdf: add capsule generation DSC/FDF Jiewen Yao
                   ` (12 subsequent siblings)
  48 siblings, 0 replies; 83+ messages in thread
From: Jiewen Yao @ 2016-09-21  6:45 UTC (permalink / raw)
  To: edk2-devel
  Cc: Michael D Kinney, Kelly Steele, Feng Tian, Star Zeng, Liming Gao,
	Chao Zhang

Add capsule and recovery support module in platform dsc and fdf.

Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Kelly Steele <kelly.steele@intel.com>
Cc: Feng Tian <feng.tian@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Chao Zhang <chao.b.zhang@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
---
 QuarkPlatformPkg/Quark.dsc    | 61 ++++++++++++++++----
 QuarkPlatformPkg/Quark.fdf    | 53 +++++++++++++++++
 QuarkPlatformPkg/QuarkMin.dsc |  7 +--
 3 files changed, 106 insertions(+), 15 deletions(-)

diff --git a/QuarkPlatformPkg/Quark.dsc b/QuarkPlatformPkg/Quark.dsc
index 51a7b63..67d0a1e 100644
--- a/QuarkPlatformPkg/Quark.dsc
+++ b/QuarkPlatformPkg/Quark.dsc
@@ -39,6 +39,8 @@
   DEFINE SOURCE_DEBUG_ENABLE  = FALSE
   DEFINE PERFORMANCE_ENABLE   = FALSE
   DEFINE LOGGING              = FALSE
+  DEFINE CAPSULE_ENABLE       = FALSE
+  DEFINE RECOVERY_ENABLE      = FALSE
 
   #
   # Galileo board.  Options are [GEN1, GEN2]
@@ -160,11 +162,9 @@
   PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf
 !endif
 
-!if $(SECURE_BOOT_ENABLE) || $(MEASURED_BOOT_ENABLE)
   OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLib.inf
   IntrinsicLib|CryptoPkg/Library/IntrinsicLib/IntrinsicLib.inf
   BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
-!endif
 
 !if $(SECURE_BOOT_ENABLE)
   PlatformSecureLib|QuarkPlatformPkg/Library/PlatformSecureLib/PlatformSecureLib.inf
@@ -226,6 +226,17 @@
   PlatformPcieHelperLib|QuarkPlatformPkg/Library/PlatformPcieHelperLib/PlatformPcieHelperLib.inf
   PlatformHelperLib|QuarkPlatformPkg/Library/PlatformHelperLib/DxePlatformHelperLib.inf
 
+!if $(CAPSULE_ENABLE)
+  CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.inf
+!else
+  CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf
+!endif
+
+  EdkiiSystemCapsuleLib|MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.inf
+  FmpAuthenticationLib|MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.inf
+  IniParsingLib|MdeModulePkg/Library/IniParsingLib/IniParsingLib.inf
+  PlatformFlashAccessLib|QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLibDxe.inf
+
 [LibraryClasses.common.SEC]
   #
   # SEC specific phase
@@ -251,9 +262,7 @@
   PlatformHelperLib|QuarkPlatformPkg/Library/PlatformHelperLib/PeiPlatformHelperLib.inf
   CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.inf
   MpInitLib|UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf
-!if $(SECURE_BOOT_ENABLE) || $(MEASURED_BOOT_ENABLE)
   BaseCryptLib|CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
-!endif
 !if $(PERFORMANCE_ENABLE)
   PerformanceLib|MdeModulePkg/Library/PeiPerformanceLib/PeiPerformanceLib.inf
 !endif
@@ -274,9 +283,7 @@
   PciLib|MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf
   CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/SmmCpuExceptionHandlerLib.inf
   SmmMemLib|MdePkg/Library/SmmMemLib/SmmMemLib.inf
-!if $(SECURE_BOOT_ENABLE) || $(MEASURED_BOOT_ENABLE)
   BaseCryptLib|CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
-!endif
 !if $(PERFORMANCE_ENABLE)
   PerformanceLib|MdeModulePkg/Library/SmmPerformanceLib/SmmPerformanceLib.inf
 !endif
@@ -302,6 +309,10 @@
   BaseCryptLib|CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf
 !endif
 
+!if $(CAPSULE_ENABLE)
+  CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf
+!endif
+
 [LibraryClasses.IA32.UEFI_DRIVER,LibraryClasses.IA32.UEFI_APPLICATION]
   PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
 
@@ -450,6 +461,11 @@
   gQuarkPlatformTokenSpaceGuid.PcdUserIsPhysicallyPresent|FALSE
   gQuarkPlatformTokenSpaceGuid.PcdSpiFlashDeviceSize|0
 
+!if $(CAPSULE_ENABLE) || $(RECOVERY_ENABLE)
+  gEfiMdeModulePkgTokenSpaceGuid.PcdEdkiiSystemFirmwareImageDescriptor|{0x0}|VOID*|0x100
+  gEfiMdeModulePkgTokenSpaceGuid.PcdEdkiiSystemFmpCapsuleImageTypeIdGuid|{0xc0, 0x20, 0xaf, 0x62, 0x16, 0x70, 0x4a, 0x42, 0x9b, 0xf8, 0x9c, 0xcc, 0x86, 0x58, 0x40, 0x90}
+!endif
+
 !if $(MEASURED_BOOT_ENABLE)
   #
   # TPM1.2      { 0x8b01e5b6, 0x4f19, 0x46e8, { 0xab, 0x93, 0x1c, 0x53, 0x67, 0x1b, 0x90, 0xcc } }
@@ -541,6 +557,11 @@
     !endif
   }
 
+!if $(CAPSULE_ENABLE) || $(RECOVERY_ENABLE)
+  # FMP image decriptor
+  QuarkPlatformPkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptor.inf
+!endif
+
   #
   # PEI Core
   #
@@ -595,6 +616,7 @@
   #
   # Recovery
   #
+!if $(RECOVERY_ENABLE)
   QuarkSocPkg/QuarkSouthCluster/Usb/Common/Pei/UsbPei.inf
   MdeModulePkg/Bus/Pci/EhciPei/EhciPei.inf
   QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/OhciPei.inf
@@ -602,6 +624,11 @@
   MdeModulePkg/Bus/Usb/UsbBusPei/UsbBusPei.inf
   FatPkg/FatPei/FatPei.inf
   MdeModulePkg/Universal/Disk/CdExpressPei/CdExpressPei.inf
+  MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPei.inf {
+    <LibraryClasses>
+      NULL|SecurityPkg/Library/FmpAuthenticationRsa2048Sha256Lib/FmpAuthenticationRsa2048Sha256Lib.inf
+  }
+!endif
 
 [Components.IA32]
   #
@@ -646,11 +673,7 @@
       NULL|MdeModulePkg/Library/VarCheckPcdLib/VarCheckPcdLib.inf
   }
 
-  MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf {
-    <LibraryClasses>
-      GenericBdsLib|IntelFrameworkModulePkg/Library/GenericBdsLib/GenericBdsLib.inf
-      CapsuleLib|IntelFrameworkModulePkg/Library/DxeCapsuleLib/DxeCapsuleLib.inf
-  }
+  MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
   MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf
   MdeModulePkg/Universal/ResetSystemRuntimeDxe/ResetSystemRuntimeDxe.inf
   PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcatRealTimeClockRuntimeDxe.inf
@@ -676,6 +699,7 @@
     <LibraryClasses>
       UefiBootManagerLib|MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf
       PlatformBootManagerLib|QuarkPlatformPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf
+      NULL|SecurityPkg/Library/FmpAuthenticationPkcs7Lib/FmpAuthenticationPkcs7Lib.inf
   }
   MdeModulePkg/Application/UiApp/UiApp.inf {
     <LibraryClasses>
@@ -885,5 +909,20 @@
       gEfiMdePkgTokenSpaceGuid.PcdUefiLibMaxPrintBufferSize|8000
   }
 
+!if $(CAPSULE_ENABLE)
+  MdeModulePkg/Universal/EsrtDxe/EsrtDxe.inf
+
+  MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxe.inf
+  MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxe.inf {
+    <LibraryClasses>
+      NULL|SecurityPkg/Library/FmpAuthenticationPkcs7Lib/FmpAuthenticationPkcs7Lib.inf
+  }
+
+  MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf {
+    <LibraryClasses>
+      PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
+  }
+!endif
+
 [BuildOptions.common.EDKII.DXE_RUNTIME_DRIVER]
   MSFT:*_*_*_DLINK_FLAGS = /ALIGN:4096
diff --git a/QuarkPlatformPkg/Quark.fdf b/QuarkPlatformPkg/Quark.fdf
index 9f51eb3..caa5736 100644
--- a/QuarkPlatformPkg/Quark.fdf
+++ b/QuarkPlatformPkg/Quark.fdf
@@ -317,6 +317,11 @@ APRIORI PEI {
 ##
 INF  UefiCpuPkg/SecCore/SecCore.inf
 
+!if $(CAPSULE_ENABLE) || $(RECOVERY_ENABLE)
+  # FMP image decriptor
+INF RuleOverride = FMP_IMAGE_DESC QuarkPlatformPkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptor.inf
+!endif
+
 INF  MdeModulePkg/Core/Pei/PeiMain.inf
 
 ##
@@ -347,12 +352,16 @@ INF  SecurityPkg/Tcg/TrEEConfig/TrEEConfigPei.inf
 INF  SecurityPkg/Tcg/TcgPei/TcgPei.inf
 !endif
 
+!if $(RECOVERY_ENABLE)
 FILE FV_IMAGE = 1E9D7604-EF45-46a0-BD8A-71AC78C17AC1 {
   SECTION PEI_DEPEX_EXP = {gEfiPeiMemoryDiscoveredPpiGuid AND gEfiPeiBootInRecoveryModePpiGuid}
   SECTION GUIDED A31280AD-481E-41B6-95E8-127F4C984779 {    # TIANO COMPRESS GUID
     SECTION FV_IMAGE = FVRECOVERY_COMPONENTS
   }
 }
+!endif
+
+!if $(RECOVERY_ENABLE)
 
 ################################################################################
 #
@@ -390,6 +399,9 @@ INF  MdeModulePkg/Bus/Usb/UsbBusPei/UsbBusPei.inf
 INF  MdeModulePkg/Bus/Usb/UsbBotPei/UsbBotPei.inf
 INF  FatPkg/FatPei/FatPei.inf
 INF  MdeModulePkg/Universal/Disk/CdExpressPei/CdExpressPei.inf
+INF  MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPei.inf
+
+!endif
 
 ################################################################################
 #
@@ -579,6 +591,11 @@ INF  SecurityPkg/Tcg/TcgDxe/TcgDxe.inf
 INF  RuleOverride = DRIVER_ACPITABLE SecurityPkg/Tcg/TcgSmm/TcgSmm.inf
 !endif
 
+!if $(CAPSULE_ENABLE)
+INF  MdeModulePkg/Universal/EsrtDxe/EsrtDxe.inf
+INF  MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxe.inf
+!endif
+
 ################################################################################
 #
 # FV Section
@@ -650,6 +667,32 @@ INF  RuleOverride = TIANOCOMPRESSED ShellPkg/Application/Shell/Shell.inf
 INF  RuleOverride = TIANOCOMPRESSED PerformancePkg/Dp_App/Dp.inf
 !endif
 
+!if $(CAPSULE_ENABLE) || $(RECOVERY_ENABLE)
+
+[FV.CapsuleDispatchFv]
+FvAlignment        = 16
+ERASE_POLARITY     = 1
+MEMORY_MAPPED      = TRUE
+STICKY_WRITE       = TRUE
+LOCK_CAP           = TRUE
+LOCK_STATUS        = TRUE
+WRITE_DISABLED_CAP = TRUE
+WRITE_ENABLED_CAP  = TRUE
+WRITE_STATUS       = TRUE
+WRITE_LOCK_CAP     = TRUE
+WRITE_LOCK_STATUS  = TRUE
+READ_DISABLED_CAP  = TRUE
+READ_ENABLED_CAP   = TRUE
+READ_STATUS        = TRUE
+READ_LOCK_CAP      = TRUE
+READ_LOCK_STATUS   = TRUE
+
+!if $(CAPSULE_ENABLE)
+INF  MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxe.inf
+!endif
+
+!endif
+
 ################################################################################
 #
 # Rules are use with the [FV] section's module INF type to define
@@ -771,3 +814,13 @@ INF  RuleOverride = TIANOCOMPRESSED PerformancePkg/Dp_App/Dp.inf
     RAW ACPI               |.acpi
     RAW ASL                |.aml
   }
+
+[Rule.Common.PEIM.FMP_IMAGE_DESC]
+  FILE PEIM = $(NAMED_GUID) {
+     RAW BIN                  |.acpi
+     PEI_DEPEX PEI_DEPEX Optional        $(INF_OUTPUT)/$(MODULE_NAME).depex
+     PE32      PE32    Align=4K          $(INF_OUTPUT)/$(MODULE_NAME).efi
+     UI       STRING="$(MODULE_NAME)" Optional
+     VERSION  STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+  }
+
diff --git a/QuarkPlatformPkg/QuarkMin.dsc b/QuarkPlatformPkg/QuarkMin.dsc
index 99ae067..05ed6e6 100644
--- a/QuarkPlatformPkg/QuarkMin.dsc
+++ b/QuarkPlatformPkg/QuarkMin.dsc
@@ -161,6 +161,8 @@
   AuthVariableLib|MdeModulePkg/Library/AuthVariableLibNull/AuthVariableLibNull.inf
 !endif
 
+  CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf
+
   #
   # CPU
   #
@@ -548,10 +550,7 @@
   MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf
   MdeModulePkg/Core/RuntimeDxe/RuntimeDxe.inf
   MdeModulePkg/Universal/Variable/EmuRuntimeDxe/EmuVariableRuntimeDxe.inf
-  MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf {
-    <LibraryClasses>
-      CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf
-  }
+  MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
   MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf
   MdeModulePkg/Universal/ResetSystemRuntimeDxe/ResetSystemRuntimeDxe.inf
   PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcatRealTimeClockRuntimeDxe.inf
-- 
2.7.4.windows.1



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

* [PATCH 37/45] QuarkPlatformPkg/dsc/fdf: add capsule generation DSC/FDF.
  2016-09-21  6:44 [PATCH 00/45] Add capsule update and recovery sample Jiewen Yao
                   ` (35 preceding siblings ...)
  2016-09-21  6:45 ` [PATCH 36/45] QuarkPlatformPkg/dsc/fdf: Add capsule/recovery support Jiewen Yao
@ 2016-09-21  6:45 ` Jiewen Yao
  2016-09-29  1:01   ` Kinney, Michael D
  2016-09-21  6:45 ` [PATCH 38/45] Vlv2TbltDevicePkg/PlatformFlashAccessLib: Add instance for capsule update Jiewen Yao
                   ` (11 subsequent siblings)
  48 siblings, 1 reply; 83+ messages in thread
From: Jiewen Yao @ 2016-09-21  6:45 UTC (permalink / raw)
  To: edk2-devel
  Cc: Michael D Kinney, Kelly Steele, Feng Tian, Star Zeng, Liming Gao,
	Chao Zhang

Add DSC/FDF to generate capsule image.
It is separated from normal DSC/FDF, because the FDF file need use
the result of final build.

Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Kelly Steele <kelly.steele@intel.com>
Cc: Feng Tian <feng.tian@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Chao Zhang <chao.b.zhang@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
---
 QuarkPlatformPkg/QuarkCapsule.dsc | 44 +++++++++++
 QuarkPlatformPkg/QuarkCapsule.fdf | 82 ++++++++++++++++++++
 2 files changed, 126 insertions(+)

diff --git a/QuarkPlatformPkg/QuarkCapsule.dsc b/QuarkPlatformPkg/QuarkCapsule.dsc
new file mode 100644
index 0000000..3785cbd
--- /dev/null
+++ b/QuarkPlatformPkg/QuarkCapsule.dsc
@@ -0,0 +1,44 @@
+## @file
+# Clanton Peak CRB platform with 32-bit DXE for 4MB/8MB flash devices.
+#
+# This package provides Clanton Peak CRB platform specific capsule.
+# Copyright (c) 2016 Intel Corporation.
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution.  The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+  PLATFORM_NAME                  = Quark
+  PLATFORM_GUID                  = 3B9F8782-0799-450C-ACB3-2D8F4504810F
+  PLATFORM_VERSION               = 0.1
+  FLASH_DEFINITION               = QuarkPlatformPkg/QuarkCapsule.fdf
+  OUTPUT_DIRECTORY               = Build/Quark
+  SUPPORTED_ARCHITECTURES        = IA32
+  BUILD_TARGETS                  = DEBUG|RELEASE
+  SKUID_IDENTIFIER               = DEFAULT
+
+###################################################################################################
+#
+# Components Section - list of the modules and components that will be processed by compilation
+#                      tools and the EDK II tools to generate PE32/PE32+/Coff image files.
+#
+# Note: The EDK II DSC file is not used to specify how compiled binary images get placed
+#       into firmware volume images. This section is just a list of modules to compile from
+#       source into UEFI-compliant binaries.
+#       It is the FDF file that contains information on combining binary files into firmware
+#       volume images, whose concept is beyond UEFI and is described in PI specification.
+#       Binary modules do not need to be listed in this section, as they should be
+#       specified in the FDF file. For example: Shell binary, FAT binary (Fat.efi),
+#       Logo (Logo.bmp), and etc.
+#       There may also be modules listed in this section that are not required in the FDF file,
+#       When a module listed here is excluded from FDF file, then UEFI-compliant binary will be
+#       generated for it, but the binary will not be put into any firmware volume.
+#
+###################################################################################################
diff --git a/QuarkPlatformPkg/QuarkCapsule.fdf b/QuarkPlatformPkg/QuarkCapsule.fdf
new file mode 100644
index 0000000..d9dac51
--- /dev/null
+++ b/QuarkPlatformPkg/QuarkCapsule.fdf
@@ -0,0 +1,82 @@
+## @file
+# FDF file of Clanton Peak CRB platform with 32-bit DXE
+#
+# This package provides QuarkNcSocId platform specific capsule.
+# Copyright (c) 2016 Intel Corporation.
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution.  The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[FV.BiosUpdateCargo]
+FvAlignment        = 16
+ERASE_POLARITY     = 1
+MEMORY_MAPPED      = TRUE
+STICKY_WRITE       = TRUE
+LOCK_CAP           = TRUE
+LOCK_STATUS        = TRUE
+WRITE_DISABLED_CAP = TRUE
+WRITE_ENABLED_CAP  = TRUE
+WRITE_STATUS       = TRUE
+WRITE_LOCK_CAP     = TRUE
+WRITE_LOCK_STATUS  = TRUE
+READ_DISABLED_CAP  = TRUE
+READ_ENABLED_CAP   = TRUE
+READ_STATUS        = TRUE
+READ_LOCK_CAP      = TRUE
+READ_LOCK_STATUS   = TRUE
+
+FILE RAW = AF9C9EB2-12AD-4D3E-A4D4-96F6C9966215 {
+    $(OUTPUT_DIRECTORY)/$(TARGET)_$(TOOL_CHAIN_TAG)/FV/QUARK.fd
+  }
+
+FILE RAW = ce57b167-b0e4-41e8-a897-5f4feb781d40 {
+    $(OUTPUT_DIRECTORY)/$(TARGET)_$(TOOL_CHAIN_TAG)/FV/CAPSULEDISPATCHFV.Fv
+  }
+
+FILE RAW = 812136D3-4D3A-433A-9418-29BB9BF78F6E {
+    QuarkPlatformPkg/Feature/Capsule/SystemBiosUpdateConfig/SystemBiosUpdateConfig.ini
+  }
+
+[FmpPayload.FmpPayloadBiosPkcs7]
+IMAGE_HEADER_INIT_VERSION = 0x02
+IMAGE_TYPE_ID             = 62af20c0-7016-424a-9bf8-9ccc86584090 # System FMP special Guid (do not change it)
+IMAGE_INDEX               = 0x1
+HARDWARE_INSTANCE         = 0x0
+MONOTONIC_COUNT           = 0x2
+CERTIFICATE_GUID          = 4AAFD29D-68DF-49EE-8AA9-347D375665A7 # PKCS7
+
+FILE DATA = $(WORKSPACE)/$(OUTPUT_DIRECTORY)/$(TARGET)_$(TOOL_CHAIN_TAG)/FV/BIOSUPDATECARGO.Fv
+
+[FmpPayload.FmpPayloadBiosRsa2048]
+IMAGE_HEADER_INIT_VERSION = 0x02
+IMAGE_TYPE_ID             = 62af20c0-7016-424a-9bf8-9ccc86584090 # System FMP special Guid (do not change it)
+IMAGE_INDEX               = 0x1
+HARDWARE_INSTANCE         = 0x0
+MONOTONIC_COUNT           = 0x2
+CERTIFICATE_GUID          = A7717414-C616-4977-9420-844712A735BF # RSA2048SHA256
+
+FILE DATA = $(WORKSPACE)/$(OUTPUT_DIRECTORY)/$(TARGET)_$(TOOL_CHAIN_TAG)/FV/BIOSUPDATECARGO.Fv
+
+[Capsule.BiosCapsuleFmpPkcs7]
+CAPSULE_GUID                = 6dcbd5ed-e82d-4c44-bda1-7194199ad92a # FMP special Guid (do not change it)
+CAPSULE_FLAGS               = PersistAcrossReset,InitiateReset
+CAPSULE_HEADER_SIZE         = 0x20
+CAPSULE_HEADER_INIT_VERSION = 0x1
+
+FMP_PAYLOAD = FmpPayloadBiosPkcs7
+
+[Capsule.BiosCapsuleFmpRsa2048]
+CAPSULE_GUID                = 6dcbd5ed-e82d-4c44-bda1-7194199ad92a # FMP special Guid (do not change it)
+CAPSULE_FLAGS               = PersistAcrossReset,InitiateReset
+CAPSULE_HEADER_SIZE         = 0x20
+CAPSULE_HEADER_INIT_VERSION = 0x1
+
+FMP_PAYLOAD = FmpPayloadBiosRsa2048
+
-- 
2.7.4.windows.1



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

* [PATCH 38/45] Vlv2TbltDevicePkg/PlatformFlashAccessLib: Add instance for capsule update.
  2016-09-21  6:44 [PATCH 00/45] Add capsule update and recovery sample Jiewen Yao
                   ` (36 preceding siblings ...)
  2016-09-21  6:45 ` [PATCH 37/45] QuarkPlatformPkg/dsc/fdf: add capsule generation DSC/FDF Jiewen Yao
@ 2016-09-21  6:45 ` Jiewen Yao
  2016-09-21  6:51   ` Wei, David
  2016-09-21  6:45 ` [PATCH 39/45] Vlv2TbltDevicePkg/SystemBiosDescriptor: Add Descriptor " Jiewen Yao
                   ` (10 subsequent siblings)
  48 siblings, 1 reply; 83+ messages in thread
From: Jiewen Yao @ 2016-09-21  6:45 UTC (permalink / raw)
  To: edk2-devel
  Cc: David Wei, Feng Tian, Star Zeng, Michael D Kinney, Liming Gao,
	Chao Zhang

Add PlatformFlashAccessLib for capsule update.

Cc: David Wei <david.wei@intel.com>
Cc: Feng Tian <feng.tian@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Chao Zhang <chao.b.zhang@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
---
 Vlv2TbltDevicePkg/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.c   | 192 ++++++++++++++++++++
 Vlv2TbltDevicePkg/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.inf |  47 +++++
 2 files changed, 239 insertions(+)

diff --git a/Vlv2TbltDevicePkg/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.c b/Vlv2TbltDevicePkg/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.c
new file mode 100644
index 0000000..ae8b171
--- /dev/null
+++ b/Vlv2TbltDevicePkg/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.c
@@ -0,0 +1,192 @@
+/** @file
+  Platform Flash Access library.
+
+  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <PiDxe.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PlatformFlashAccessLib.h>
+#include <Library/FlashDeviceLib.h>
+#include <Library/MemoryAllocationLib.h>
+
+#define SECTOR_SIZE_64KB  0x10000      // Common 64kBytes sector size
+#define ALINGED_SIZE  SECTOR_SIZE_64KB
+
+STATIC EFI_PHYSICAL_ADDRESS     mInternalFdAddress;
+
+/**
+  Perform flash write opreation.
+
+  @param FirmwareType      The type of firmware.
+  @param FlashAddress      The address of flash device to be accessed.
+  @param FlashAddressType  The type of flash device address.
+  @param Buffer            The pointer to the data buffer.
+  @param Length            The length of data buffer in bytes.
+
+  @retval EFI_SUCCESS           The operation returns successfully.
+  @retval EFI_WRITE_PROTECTED   The flash device is read only.
+  @retval EFI_UNSUPPORTED       The flash device access is unsupported.
+  @retval EFI_INVALID_PARAMETER The input parameter is not valid.
+**/
+EFI_STATUS
+EFIAPI
+PerformFlashWrite(
+  IN PLATFORM_FIRMWARE_TYPE       FirmwareType,
+  IN EFI_PHYSICAL_ADDRESS         FlashAddress,
+  IN FLASH_ADDRESS_TYPE           FlashAddressType,
+  IN VOID                         *Buffer,
+  IN UINTN                        Length
+  )
+{
+  EFI_STATUS          Status;
+
+  DEBUG((EFI_D_INFO, "PerformFlashWrite - 0x%x(%x) - 0x%x\n", (UINTN)FlashAddress, (UINTN)FlashAddressType, Length));
+  if (FirmwareType >= PlatformFirmwareTypeMax) {
+    return EFI_UNSUPPORTED;
+  }
+  if (FlashAddressType == FlashAddressTypeRelativeAddress) {
+    FlashAddress = FlashAddress + mInternalFdAddress;
+  }
+
+  LibFvbFlashDeviceBlockLock(FlashAddress, Length, FALSE);
+
+  //
+  // Erase & Write
+  //
+  Status = LibFvbFlashDeviceBlockErase((UINTN)FlashAddress, Length);
+  ASSERT_EFI_ERROR(Status);
+  if (EFI_ERROR(Status)) {
+    LibFvbFlashDeviceBlockLock(FlashAddress, Length, TRUE);
+    DEBUG((EFI_D_ERROR, "Flash Erase error\n"));
+    return Status;
+  }
+
+  Status = LibFvbFlashDeviceWrite((UINTN)FlashAddress, &Length, Buffer);
+  ASSERT_EFI_ERROR(Status);
+  if (EFI_ERROR(Status)) {
+    LibFvbFlashDeviceBlockLock(FlashAddress, Length, TRUE);
+    DEBUG((EFI_D_ERROR, "Flash write error\n"));
+    return Status;
+  }
+
+  LibFvbFlashDeviceBlockLock(FlashAddress, Length, TRUE);
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Perform microcode write opreation.
+
+  @param FlashAddress      The address of flash device to be accessed.
+  @param Buffer            The pointer to the data buffer.
+  @param Length            The length of data buffer in bytes.
+
+  @retval EFI_SUCCESS           The operation returns successfully.
+  @retval EFI_WRITE_PROTECTED   The flash device is read only.
+  @retval EFI_UNSUPPORTED       The flash device access is unsupported.
+  @retval EFI_INVALID_PARAMETER The input parameter is not valid.
+**/
+EFI_STATUS
+EFIAPI
+MicrocodeFlashWrite(
+  IN EFI_PHYSICAL_ADDRESS         FlashAddress,
+  IN VOID                         *Buffer,
+  IN UINTN                        Length
+  )
+{
+  EFI_PHYSICAL_ADDRESS         AlignedFlashAddress;
+  VOID                         *AlignedBuffer;
+  UINTN                        AlignedLength;
+  UINTN                        OffsetHead;
+  UINTN                        OffsetTail;
+  EFI_STATUS                   Status;
+
+  DEBUG((EFI_D_INFO, "MicrocodeFlashWrite - 0x%x - 0x%x\n", (UINTN)FlashAddress, Length));
+
+  //
+  // Need make buffer 64K aligned to support ERASE
+  //
+  // [Aligned]    FlashAddress    [Aligned]
+  // |              |                     |
+  // V              V                     V
+  // +--------------+========+------------+
+  // | OffsetHeader | Length | OffsetTail |
+  // +--------------+========+------------+
+  // ^
+  // |<-----------AlignedLength----------->
+  // |
+  // AlignedFlashAddress
+  //
+  OffsetHead = FlashAddress & (ALINGED_SIZE - 1);
+  OffsetTail = (FlashAddress + Length) & (ALINGED_SIZE - 1);
+  if (OffsetTail != 0) {
+    OffsetTail = ALINGED_SIZE - OffsetTail;
+  }
+
+  if ((OffsetHead != 0) || (OffsetTail != 0)) {
+    AlignedFlashAddress = FlashAddress - OffsetHead;
+    AlignedLength = Length + OffsetHead + OffsetTail;
+
+    AlignedBuffer = AllocatePool(AlignedLength);
+    if (AlignedBuffer == NULL) {
+      return EFI_OUT_OF_RESOURCES;
+    }
+    //
+    // Save original buffer
+    //
+    if (OffsetHead != 0) {
+      CopyMem((UINT8 *)AlignedBuffer, (VOID *)AlignedFlashAddress, OffsetHead);
+    }
+    if (OffsetTail != 0) {
+      CopyMem((UINT8 *)AlignedBuffer + OffsetHead + Length, (VOID *)(AlignedFlashAddress + OffsetHead + Length), OffsetTail);
+    }
+    //
+    // Override new buffer
+    //
+    CopyMem((UINT8 *)AlignedBuffer + OffsetHead, Buffer, Length);
+  } else {
+    AlignedFlashAddress = FlashAddress;
+    AlignedBuffer = Buffer;
+    AlignedLength = Length;
+  }
+
+  Status = PerformFlashWrite(
+             PlatformFirmwareTypeBios,
+             AlignedFlashAddress,
+             FlashAddressTypeAbsoluteAddress,
+             AlignedBuffer,
+             AlignedLength
+             );
+  if ((OffsetHead != 0) || (OffsetTail != 0)) {
+    FreePool (AlignedBuffer);
+  }
+  return Status;
+}
+
+/**
+  Platform Flash Access Lib Constructor.
+**/
+EFI_STATUS
+EFIAPI
+PerformFlashAccessLibConstructor (
+  VOID
+  )
+{
+  mInternalFdAddress = FixedPcdGet64(PcdFlashAreaBaseAddress);
+  DEBUG((EFI_D_INFO, "PcdFlashAreaBaseAddress - 0x%x\n", mInternalFdAddress));
+
+  return EFI_SUCCESS;
+}
diff --git a/Vlv2TbltDevicePkg/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.inf b/Vlv2TbltDevicePkg/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.inf
new file mode 100644
index 0000000..18c2809
--- /dev/null
+++ b/Vlv2TbltDevicePkg/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.inf
@@ -0,0 +1,47 @@
+## @file
+#  Platform Flash Access library.
+#
+#  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = PlatformFlashAccessLib
+  FILE_GUID                      = 31CF9CEC-DA4E-4505-AA20-33364A291A95
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = PlatformFlashAccessLib
+  LIBRARY_CLASS                  = MicrocodeFlashAccessLib
+  CONSTRUCTOR                    = PerformFlashAccessLibConstructor
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64 IPF EBC
+#
+
+[Sources]
+  PlatformFlashAccessLib.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  Vlv2TbltDevicePkg/PlatformPkg.dec
+
+[LibraryClasses]
+  BaseMemoryLib
+  PcdLib
+  DebugLib
+  FlashDeviceLib
+  MemoryAllocationLib
+
+[FixedPcd]
+  gPlatformModuleTokenSpaceGuid.PcdFlashAreaBaseAddress
-- 
2.7.4.windows.1



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

* [PATCH 39/45] Vlv2TbltDevicePkg/SystemBiosDescriptor: Add Descriptor for capsule update.
  2016-09-21  6:44 [PATCH 00/45] Add capsule update and recovery sample Jiewen Yao
                   ` (37 preceding siblings ...)
  2016-09-21  6:45 ` [PATCH 38/45] Vlv2TbltDevicePkg/PlatformFlashAccessLib: Add instance for capsule update Jiewen Yao
@ 2016-09-21  6:45 ` Jiewen Yao
  2016-09-21  6:54   ` Wei, David
  2016-09-21  6:45 ` [PATCH 40/45] Vlv2TbltDevicePkg/SystemBiosUpdateConfig: Add capsule config file Jiewen Yao
                   ` (9 subsequent siblings)
  48 siblings, 1 reply; 83+ messages in thread
From: Jiewen Yao @ 2016-09-21  6:45 UTC (permalink / raw)
  To: edk2-devel
  Cc: David Wei, Feng Tian, Star Zeng, Michael D Kinney, Liming Gao,
	Chao Zhang

Add SystemBiosDescriptor for capsule update.
The PEIM extracts SystemBiosDescriptor info from FFS and reports it via PCD.

Cc: David Wei <david.wei@intel.com>
Cc: Feng Tian <feng.tian@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Chao Zhang <chao.b.zhang@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
---
 Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptor.aslc | 86 ++++++++++++++++++++
 Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptor.inf  | 45 ++++++++++
 Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptorPei.c | 66 +++++++++++++++
 3 files changed, 197 insertions(+)

diff --git a/Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptor.aslc b/Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptor.aslc
new file mode 100644
index 0000000..a989a7c
--- /dev/null
+++ b/Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptor.aslc
@@ -0,0 +1,86 @@
+/** @file
+  System BIOS descriptor.
+
+  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <PiPei.h>
+#include <Protocol/FirmwareManagement.h>
+#include <Guid/EdkiiSystemFmpCapsule.h>
+
+#define PACKAGE_VERSION                     0xFFFFFFFF
+#define PACKAGE_VERSION_STRING              L"Unknown"
+
+#define CURRENT_FIRMWARE_VERSION            0x00000002
+#define CURRENT_FIRMWARE_VERSION_STRING     L"0x00000002"
+#define LOWEST_SUPPORTED_FIRMWARE_VERSION   0x00000001
+
+#define IMAGE_ID                            SIGNATURE_64('V', 'L', 'V', '2', '_', '_', 'F', 'd')
+#define IMAGE_ID_STRING                     L"Vlv2Fd"
+
+#define IMAGE_TYPE_ID_GUID                  { 0x4096267b, 0xda0a, 0x42eb, { 0xb5, 0xeb, 0xfe, 0xf3, 0x1d, 0x20, 0x7c, 0xb4 } }
+
+typedef struct {
+  EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR  Descriptor;
+  // real string data
+  CHAR16                                  ImageIdNameStr[16];
+  CHAR16                                  VersionNameStr[16];
+  CHAR16                                  PackageVersionNameStr[16];
+} IMAGE_DESCRIPTOR;
+
+IMAGE_DESCRIPTOR mImageDescriptor =
+{
+  {
+    EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR_SIGNATURE,
+    sizeof(EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR),
+    sizeof(IMAGE_DESCRIPTOR),
+    PACKAGE_VERSION,                                       // PackageVersion
+    OFFSET_OF (IMAGE_DESCRIPTOR, PackageVersionNameStr),   // PackageVersionName
+    1,                                                     // ImageIndex;
+    {0x0},                                                 // Reserved
+    IMAGE_TYPE_ID_GUID,                                    // ImageTypeId;
+    IMAGE_ID,                                              // ImageId;
+    OFFSET_OF (IMAGE_DESCRIPTOR, ImageIdNameStr),          // ImageIdName;
+    CURRENT_FIRMWARE_VERSION,                              // Version;
+    OFFSET_OF (IMAGE_DESCRIPTOR, VersionNameStr),          // VersionName;
+    {0x0},                                                 // Reserved2
+    FixedPcdGet32(PcdFlashAreaSize),                       // Size;
+    IMAGE_ATTRIBUTE_IMAGE_UPDATABLE |
+      IMAGE_ATTRIBUTE_RESET_REQUIRED |
+      IMAGE_ATTRIBUTE_IN_USE,                              // AttributesSupported;
+    IMAGE_ATTRIBUTE_IMAGE_UPDATABLE |
+      IMAGE_ATTRIBUTE_RESET_REQUIRED |
+      IMAGE_ATTRIBUTE_IN_USE,                              // AttributesSetting;
+    0x0,                                                   // Compatibilities;
+    LOWEST_SUPPORTED_FIRMWARE_VERSION,                     // LowestSupportedImageVersion;
+    0x00000000,                                            // LastAttemptVersion;
+    0,                                                     // LastAttemptStatus;
+    {0x0},                                                 // Reserved3
+    0,                                                     // HardwareInstance;
+  },
+  // real string data
+  {IMAGE_ID_STRING},
+  {CURRENT_FIRMWARE_VERSION_STRING},
+  {PACKAGE_VERSION_STRING},
+};
+
+
+VOID*
+ReferenceAcpiTable (
+  VOID
+  )
+{
+  //
+  // Reference the table being generated to prevent the optimizer from
+  // removing the data structure from the executable
+  //
+  return (VOID*)&mImageDescriptor;
+}
diff --git a/Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptor.inf b/Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptor.inf
new file mode 100644
index 0000000..812d272
--- /dev/null
+++ b/Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptor.inf
@@ -0,0 +1,45 @@
+## @file
+#  System BIOS descriptor.
+#
+#  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = SystemBiosDescriptor
+  FILE_GUID                      = 90B2B846-CA6D-4D6E-A8D3-C140A8E110AC
+  MODULE_TYPE                    = PEIM
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = SystemBiosDescriptorPeimEntry
+
+[Sources]
+  SystemBiosDescriptorPei.c
+  SystemBiosDescriptor.aslc
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  Vlv2TbltDevicePkg/PlatformPkg.dec
+
+[LibraryClasses]
+  PcdLib
+  PeiServicesLib
+  DebugLib
+  PeimEntryPoint
+
+[FixedPcd]
+  gPlatformModuleTokenSpaceGuid.PcdFlashAreaSize
+
+[Pcd]
+  gEfiMdeModulePkgTokenSpaceGuid.PcdEdkiiSystemFirmwareImageDescriptor
+
+[Depex]
+  TRUE
diff --git a/Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptorPei.c b/Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptorPei.c
new file mode 100644
index 0000000..6272138
--- /dev/null
+++ b/Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptorPei.c
@@ -0,0 +1,66 @@
+/** @file
+  System BIOS descriptor producer.
+
+  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <PiPei.h>
+#include <Library/PcdLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/DebugLib.h>
+#include <Protocol/FirmwareManagement.h>
+#include <Guid/EdkiiSystemFmpCapsule.h>
+
+/**
+  Entrypoint for SystemBiosDescriptor PEIM.
+
+  @param  FileHandle  Handle of the file being invoked.
+  @param  PeiServices Describes the list of possible PEI Services.
+
+  @retval EFI_SUCCESS            PPI successfully installed.
+**/
+EFI_STATUS
+EFIAPI
+SystemBiosDescriptorPeimEntry(
+  IN EFI_PEI_FILE_HANDLE     FileHandle,
+  IN CONST EFI_PEI_SERVICES  **PeiServices
+  )
+{
+  EFI_STATUS                              Status;
+  EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR  *Descriptor;
+  UINTN                                   Size;
+  UINTN                                   Index;
+  UINT32                                  AuthenticationStatus;
+
+  //
+  // Search RAW section.
+  //
+  Index = 0;
+  while (TRUE) {
+    Status = PeiServicesFfsFindSectionData3(EFI_SECTION_RAW, Index, FileHandle, &Descriptor, &AuthenticationStatus);
+    if (EFI_ERROR(Status)) {
+      // Should not happen, must something wrong in FDF.
+      ASSERT(FALSE);
+      return EFI_NOT_FOUND;
+    }
+    if (Descriptor->Signature == EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR_SIGNATURE) {
+      break;
+    }
+    Index++;
+  }
+
+  DEBUG((EFI_D_INFO, "EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR size - 0x%x\n", Descriptor->Length));
+
+  Size = Descriptor->Length;
+  PcdSetPtrS (PcdEdkiiSystemFirmwareImageDescriptor, &Size, Descriptor);
+
+  return EFI_SUCCESS;
+}
-- 
2.7.4.windows.1



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

* [PATCH 40/45] Vlv2TbltDevicePkg/SystemBiosUpdateConfig: Add capsule config file.
  2016-09-21  6:44 [PATCH 00/45] Add capsule update and recovery sample Jiewen Yao
                   ` (38 preceding siblings ...)
  2016-09-21  6:45 ` [PATCH 39/45] Vlv2TbltDevicePkg/SystemBiosDescriptor: Add Descriptor " Jiewen Yao
@ 2016-09-21  6:45 ` Jiewen Yao
  2016-09-21  6:57   ` Wei, David
  2016-09-21  6:45 ` [PATCH 41/45] Vlv2TbltDevicePkg/FlashDeviceLib: Add DXE flash device lib Jiewen Yao
                   ` (8 subsequent siblings)
  48 siblings, 1 reply; 83+ messages in thread
From: Jiewen Yao @ 2016-09-21  6:45 UTC (permalink / raw)
  To: edk2-devel
  Cc: David Wei, Feng Tian, Star Zeng, Michael D Kinney, Liming Gao,
	Chao Zhang

Add SystemBiosUpdateConfig as capsule configuration file.

Cc: David Wei <david.wei@intel.com>
Cc: Feng Tian <feng.tian@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Chao Zhang <chao.b.zhang@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
---
 Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosUpdateConfig/SystemBiosUpdateConfig.ini    | 72 ++++++++++++++++++++
 Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosUpdateConfig/SystemBiosUpdateConfigGcc.ini | 72 ++++++++++++++++++++
 2 files changed, 144 insertions(+)

diff --git a/Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosUpdateConfig/SystemBiosUpdateConfig.ini b/Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosUpdateConfig/SystemBiosUpdateConfig.ini
new file mode 100644
index 0000000..61e254b
--- /dev/null
+++ b/Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosUpdateConfig/SystemBiosUpdateConfig.ini
@@ -0,0 +1,72 @@
+## @file
+#
+#  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Head]
+NumOfUpdate = 6
+NumOfRecovery = 1
+Update0 = Vlv2FvMicrocode
+Update1 = Vlv2FvBinary
+Update2 = Vlv2FvMain
+Update3 = Vlv2FvRecovery2
+Update4 = Vlv2FvRecovery
+Update5 = Vlv2FvNvRam
+Recovery0 = Vlv2FvMain
+
+[Vlv2FvMicrocode]
+FirmwareType = 0            # BIOS
+AddressType = 0             # 0 - relative address, 1 - absolute address.
+BaseAddress = 0x00000000    # Base address offset on flash
+Length      = 0x00040000    # Length
+ImageOffset = 0x00000000    # Image offset of this BIOS update image
+FileGuid    = AF9C9EB2-12AD-4D3E-A4D4-96F6C9966215
+
+[Vlv2FvNvRam]
+UpdateType  = 0             # UpdateWholeFV
+AddressType = 0             # 0 - relative address, 1 - absolute address.
+BaseAddress = 0x00040000    # Base address offset on flash
+Length      = 0x00080000    # Length
+ImageOffset = 0x00040000    # Image offset of this BIOS update image
+FileGuid    = AF9C9EB2-12AD-4D3E-A4D4-96F6C9966215
+
+[Vlv2FvBinary]
+FirmwareType = 0            # BIOS
+AddressType = 0             # 0 - relative address, 1 - absolute address.
+BaseAddress = 0x000C0000    # Base address offset on flash
+Length      = 0x00050000    # Length
+ImageOffset = 0x000C0000    # Image offset of this BIOS update image
+FileGuid    = AF9C9EB2-12AD-4D3E-A4D4-96F6C9966215
+
+[Vlv2FvMain]
+FirmwareType = 1            # NvRam
+AddressType = 0             # 0 - relative address, 1 - absolute address.
+BaseAddress = 0x00110000    # Base address offset on flash
+Length      = 0x00210000    # Length
+ImageOffset = 0x00110000    # Image offset of this BIOS update image
+FileGuid    = AF9C9EB2-12AD-4D3E-A4D4-96F6C9966215
+
+[Vlv2FvRecovery2]
+FirmwareType = 0            # BIOS
+AddressType = 0             # 0 - relative address, 1 - absolute address.
+BaseAddress = 0x00320000    # Base address offset on flash
+Length      = 0x00070000    # Length
+ImageOffset = 0x00320000    # Image offset of this BIOS update image
+FileGuid    = AF9C9EB2-12AD-4D3E-A4D4-96F6C9966215
+
+[Vlv2FvRecovery]
+FirmwareType = 0            # BIOS
+AddressType = 0             # 0 - relative address, 1 - absolute address.
+BaseAddress = 0x00390000    # Base address offset on flash
+Length      = 0x00070000    # Length
+ImageOffset = 0x00390000    # Image offset of this BIOS update image
+FileGuid    = AF9C9EB2-12AD-4D3E-A4D4-96F6C9966215
+
diff --git a/Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosUpdateConfig/SystemBiosUpdateConfigGcc.ini b/Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosUpdateConfig/SystemBiosUpdateConfigGcc.ini
new file mode 100644
index 0000000..40216d4
--- /dev/null
+++ b/Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosUpdateConfig/SystemBiosUpdateConfigGcc.ini
@@ -0,0 +1,72 @@
+## @file
+#
+#  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Head]
+NumOfUpdate = 6
+NumOfRecovery = 1
+Update0 = Vlv2FvMicrocode
+Update1 = Vlv2FvBinary
+Update2 = Vlv2FvMain
+Update3 = Vlv2FvRecovery2
+Update4 = Vlv2FvRecovery
+Update5 = Vlv2FvNvRam
+Recovery0 = Vlv2FvMain
+
+[Vlv2FvMicrocode]
+FirmwareType = 0            # BIOS
+AddressType = 0             # 0 - relative address, 1 - absolute address.
+BaseAddress = 0x00000000    # Base address offset on flash
+Length      = 0x00040000    # Length
+ImageOffset = 0x00000000    # Image offset of this BIOS update image
+FileGuid    = AF9C9EB2-12AD-4D3E-A4D4-96F6C9966215
+
+[Vlv2FvNvRam]
+UpdateType  = 0             # UpdateWholeFV
+AddressType = 0             # 0 - relative address, 1 - absolute address.
+BaseAddress = 0x00040000    # Base address offset on flash
+Length      = 0x00080000    # Length
+ImageOffset = 0x00040000    # Image offset of this BIOS update image
+FileGuid    = AF9C9EB2-12AD-4D3E-A4D4-96F6C9966215
+
+[Vlv2FvBinary]
+FirmwareType = 0            # BIOS
+AddressType = 0             # 0 - relative address, 1 - absolute address.
+BaseAddress = 0x000C0000    # Base address offset on flash
+Length      = 0x00050000    # Length
+ImageOffset = 0x000C0000    # Image offset of this BIOS update image
+FileGuid    = AF9C9EB2-12AD-4D3E-A4D4-96F6C9966215
+
+[Vlv2FvMain]
+FirmwareType = 1            # NvRam
+AddressType = 0             # 0 - relative address, 1 - absolute address.
+BaseAddress = 0x00110000    # Base address offset on flash
+Length      = 0x00215000    # Length
+ImageOffset = 0x00110000    # Image offset of this BIOS update image
+FileGuid    = AF9C9EB2-12AD-4D3E-A4D4-96F6C9966215
+
+[Vlv2FvRecovery2]
+FirmwareType = 0            # BIOS
+AddressType = 0             # 0 - relative address, 1 - absolute address.
+BaseAddress = 0x00325000    # Base address offset on flash
+Length      = 0x0006B000    # Length
+ImageOffset = 0x00325000    # Image offset of this BIOS update image
+FileGuid    = AF9C9EB2-12AD-4D3E-A4D4-96F6C9966215
+
+[Vlv2FvRecovery]
+FirmwareType = 0            # BIOS
+AddressType = 0             # 0 - relative address, 1 - absolute address.
+BaseAddress = 0x00390000    # Base address offset on flash
+Length      = 0x00070000    # Length
+ImageOffset = 0x00390000    # Image offset of this BIOS update image
+FileGuid    = AF9C9EB2-12AD-4D3E-A4D4-96F6C9966215
+
-- 
2.7.4.windows.1



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

* [PATCH 41/45] Vlv2TbltDevicePkg/FlashDeviceLib: Add DXE flash device lib.
  2016-09-21  6:44 [PATCH 00/45] Add capsule update and recovery sample Jiewen Yao
                   ` (39 preceding siblings ...)
  2016-09-21  6:45 ` [PATCH 40/45] Vlv2TbltDevicePkg/SystemBiosUpdateConfig: Add capsule config file Jiewen Yao
@ 2016-09-21  6:45 ` Jiewen Yao
  2016-09-21  7:10   ` Wei, David
  2016-09-21  6:45 ` [PATCH 42/45] Vlv2TbltDevicePkg/PlatformBootManager: Add capsule/recovery handling Jiewen Yao
                   ` (7 subsequent siblings)
  48 siblings, 1 reply; 83+ messages in thread
From: Jiewen Yao @ 2016-09-21  6:45 UTC (permalink / raw)
  To: edk2-devel
  Cc: David Wei, Feng Tian, Star Zeng, Michael D Kinney, Liming Gao,
	Chao Zhang

Previous FlashDeviceLib only supports DxeRuntime and Smm.
It cannot be linked with SystemBiosUpdateDxe driver.

So we separate DxeRuntime related code into a standalone file,
and create FlashDeviceLibDxe.inf.

Cc: David Wei <david.wei@intel.com>
Cc: Feng Tian <feng.tian@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Chao Zhang <chao.b.zhang@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
---
 Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLib.c              | 156 +---------------
 Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLib.inf            |   8 +-
 Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLibDxe.c           |  62 +++++++
 Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLibDxe.inf         |  49 +++++
 Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLibDxeRuntimeSmm.c | 188 ++++++++++++++++++++
 Vlv2TbltDevicePkg/Library/FlashDeviceLib/SpiChipDefinitions.h          |   5 +-
 6 files changed, 312 insertions(+), 156 deletions(-)

diff --git a/Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLib.c b/Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLib.c
index afb12c9..d964aa5 100644
--- a/Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLib.c
+++ b/Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLib.c
@@ -1,6 +1,6 @@
 /** @file
 
-  Copyright (c) 2004  - 2014, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2004  - 2016, Intel Corporation. All rights reserved.<BR>
                                                                                    

   This program and the accompanying materials are licensed and made available under

   the terms and conditions of the BSD License that accompanies this distribution.  

@@ -19,14 +19,13 @@
 #include <Library/FlashDeviceLib.h>
 #include <Library/DebugLib.h>
 #include <Library/BaseLib.h>
-#include <Library/UefiBootServicesTableLib.h>
-#include <Library/UefiRuntimeServicesTableLib.h>
 #include <Library/BaseMemoryLib.h>
-#include <Library/UefiRuntimeLib.h>
-#include <Protocol/SmmBase2.h>
 #include <Guid/EventGroup.h>
-#include "SpiChipDefinitions.h"
+#include <Library/SpiFlash.H>
 
+#define FLASH_SIZE  0x400000
+
+#define FLASH_DEVICE_BASE_ADDRESS (0xFFFFFFFF-FLASH_SIZE+1)
 UINTN FlashDeviceBase = FLASH_DEVICE_BASE_ADDRESS;
 
 EFI_SPI_PROTOCOL *mSpiProtocol = NULL;
@@ -320,148 +319,3 @@ LibFvbFlashDeviceBlockLock (
   return Status;
 }
 
-VOID
-EFIAPI
-LibFvbFlashDeviceVirtualAddressChangeNotifyEvent (
-  IN EFI_EVENT        Event,
-  IN VOID             *Context
-  )
-{
-  gRT->ConvertPointer (0, (VOID **) &mSpiProtocol);
-  gRT->ConvertPointer (0, (VOID **) &FlashDeviceBase);
-}
-
-
-/**
-  The library constructuor.
-
-  The function does the necessary initialization work for this library
-  instance. Please put all initialization works in it.
-
-  @param[in]  ImageHandle       The firmware allocated handle for the UEFI image.
-  @param[in]  SystemTable       A pointer to the EFI system table.
-
-  @retval     EFI_SUCCESS       The function always return EFI_SUCCESS for now.
-                                It will ASSERT on error for debug version.
-  @retval     EFI_ERROR         Please reference LocateProtocol for error code details.
-
-**/
-EFI_STATUS
-EFIAPI
-LibFvbFlashDeviceSupportInit (
-  IN EFI_HANDLE         ImageHandle,
-  IN EFI_SYSTEM_TABLE   *SystemTable
-  )
-{
-  EFI_STATUS Status;
-  EFI_EVENT  Event;
-  UINT8                         SfId[3];
-  UINT8                         FlashIndex;
-  UINT8                         SpiReadError;
-  UINT8                         SpiNotMatchError;
-  EFI_SMM_BASE2_PROTOCOL       *SmmBase;
-  BOOLEAN                       InSmm;
-
-  SpiReadError     = 0x00;
-  SpiNotMatchError = 0x00;
-
-  InSmm = FALSE;
-  Status = gBS->LocateProtocol (
-                  &gEfiSmmBase2ProtocolGuid,
-                  NULL,
-                  (void **)&SmmBase
-                  );
-  if (!EFI_ERROR(Status)) {
-    Status = SmmBase->InSmm(SmmBase, &InSmm);
-    if (EFI_ERROR(Status)) {
-      InSmm = FALSE;
-    }
-  }
-
-  if (!InSmm) {
-    Status = gBS->LocateProtocol (
-                  &gEfiSpiProtocolGuid,
-                  NULL,
-                  (VOID **)&mSpiProtocol
-                  );
-    ASSERT_EFI_ERROR (Status);
-
-    Status = gBS->CreateEventEx (
-                  EVT_NOTIFY_SIGNAL,
-                  TPL_NOTIFY,
-                  LibFvbFlashDeviceVirtualAddressChangeNotifyEvent,
-                  NULL,
-                  &gEfiEventVirtualAddressChangeGuid,
-                  &Event
-                  );
-    ASSERT_EFI_ERROR (Status);
-  } else {
-    Status = gBS->LocateProtocol (
-                    &gEfiSmmSpiProtocolGuid,
-                    NULL,
-                    (VOID **)&mSpiProtocol
-                    );
-    ASSERT_EFI_ERROR (Status);
-  }
-
-
-  for (FlashIndex = EnumSpiFlashW25Q64; FlashIndex < EnumSpiFlashMax; FlashIndex++) {
-    Status = mSpiProtocol->Init (mSpiProtocol, &(mInitTable[FlashIndex]));
-    if (!EFI_ERROR (Status)) {
-      //
-      // Read Vendor/Device IDs to check if the driver supports the Serial Flash device.
-      //
-      Status = mSpiProtocol->Execute (
-                               mSpiProtocol,
-                               SPI_READ_ID,
-                               SPI_WREN,
-                               TRUE,
-                               FALSE,
-                               FALSE,
-                               0,
-                               3,
-                               SfId,
-                               EnumSpiRegionAll
-                               );
-      if (!EFI_ERROR (Status)) {
-        if ((SfId[0] == mInitTable[FlashIndex].VendorId)  &&
-            (SfId[1] == mInitTable[FlashIndex].DeviceId0) &&
-            (SfId[2] == mInitTable[FlashIndex].DeviceId1)) {
-            //
-            // Found a matching SPI device, FlashIndex now contains flash device.
-            //
-            DEBUG ((EFI_D_ERROR, "OK - Found SPI Flash Type in SPI Flash Driver, Device Type ID 0 = 0x%02x!\n", mInitTable[FlashIndex].DeviceId0));
-            DEBUG ((EFI_D_ERROR, "Device Type ID 1 = 0x%02x!\n", mInitTable[FlashIndex].DeviceId1));
-
-            if (mInitTable[FlashIndex].BiosStartOffset == (UINTN) (-1)) {
-              DEBUG ((EFI_D_ERROR, "ERROR - The size of BIOS image is bigger than SPI Flash device!\n"));
-              CpuDeadLoop ();
-            }
-            break;
-        } else {
-          SpiNotMatchError++;
-        }
-      } else {
-        SpiReadError++;
-      }
-    }
-  }
-
-  DEBUG ((EFI_D_ERROR, "SPI flash chip VID = 0x%X, DID0 = 0x%X, DID1 = 0x%X\n", SfId[0], SfId[1], SfId[2]));
-
-  if (FlashIndex < EnumSpiFlashMax)  {
-    return EFI_SUCCESS;
-  } else {
-  if (SpiReadError != 0) {
-      DEBUG ((EFI_D_ERROR, "ERROR - SPI Read ID execution failed! Error Count = %d\n", SpiReadError));
-   }    
-    else {
-      if (SpiNotMatchError != 0) {
-        DEBUG ((EFI_D_ERROR, "ERROR - No supported SPI flash chip found! Error Count = %d\n", SpiNotMatchError));
-        DEBUG ((EFI_D_ERROR, "SPI flash chip VID = 0x%X, DID0 = 0x%X, DID1 = 0x%X\n", SfId[0], SfId[1], SfId[2]));
-      }
-    }
-    return EFI_UNSUPPORTED;
-  }
-}
-
diff --git a/Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLib.inf b/Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLib.inf
index 423490e..cddbe60 100644
--- a/Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLib.inf
+++ b/Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLib.inf
@@ -1,6 +1,6 @@
 #
 #
-# Copyright (c)  1999  - 2014, Intel Corporation. All rights reserved
+# Copyright (c)  1999  - 2016, Intel Corporation. All rights reserved
 #                                                                                  

 # This program and the accompanying materials are licensed and made available under

 # the terms and conditions of the BSD License that accompanies this distribution.  

@@ -16,7 +16,7 @@
 
 [Defines]
   INF_VERSION                    = 0x00010005
-  BASE_NAME                      = FlashDeviceLib
+  BASE_NAME                      = FlashDeviceLibRuntimeSmm
   FILE_GUID                      = E38A1C3C-928C-4bf7-B6C1-7F0EF163FAA5
   MODULE_TYPE                    = DXE_DRIVER
   VERSION_STRING                 = 1.0
@@ -32,6 +32,7 @@
 
 [Sources]
   FlashDeviceLib.c
+  FlashDeviceLibDxeRuntimeSmm.c
 
 
 [Packages]
@@ -43,6 +44,9 @@
 [LibraryClasses]
   DebugLib
 
+[Guids]
+  gEfiEventVirtualAddressChangeGuid
+
 [Protocols]
   gEfiSpiProtocolGuid
   gEfiSmmSpiProtocolGuid
diff --git a/Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLibDxe.c b/Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLibDxe.c
new file mode 100644
index 0000000..bff9823
--- /dev/null
+++ b/Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLibDxe.c
@@ -0,0 +1,62 @@
+/** @file
+
+  Copyright (c) 2004  - 2016, Intel Corporation. All rights reserved.<BR>
+                                                                                   

+  This program and the accompanying materials are licensed and made available under

+  the terms and conditions of the BSD License that accompanies this distribution.  

+  The full text of the license may be found at                                     

+  http://opensource.org/licenses/bsd-license.php.                                  

+                                                                                   

+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,            

+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.    

+                                                                                   

+
+
+**/
+
+#include <PiDxe.h>
+
+#include <Library/FlashDeviceLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/BaseMemoryLib.h>
+#include "SpiChipDefinitions.h"
+
+extern UINTN FlashDeviceBase;
+
+extern EFI_SPI_PROTOCOL *mSpiProtocol;
+
+/**
+  The library constructuor.
+
+  The function does the necessary initialization work for this library
+  instance. Please put all initialization works in it.
+
+  @param[in]  ImageHandle       The firmware allocated handle for the UEFI image.
+  @param[in]  SystemTable       A pointer to the EFI system table.
+
+  @retval     EFI_SUCCESS       The function always return EFI_SUCCESS for now.
+                                It will ASSERT on error for debug version.
+  @retval     EFI_ERROR         Please reference LocateProtocol for error code details.
+
+**/
+EFI_STATUS
+EFIAPI
+LibFvbFlashDeviceSupportInit (
+  IN EFI_HANDLE         ImageHandle,
+  IN EFI_SYSTEM_TABLE   *SystemTable
+  )
+{
+  EFI_STATUS Status;
+  Status = gBS->LocateProtocol (
+                  &gEfiSpiProtocolGuid,
+                  NULL,
+                  (VOID **)&mSpiProtocol
+                  );
+  ASSERT_EFI_ERROR (Status);
+  // There is no need to call Init, because Runtime or SMM FVB already does that.
+  DEBUG((EFI_D_ERROR, "LibFvbFlashDeviceSupportInit - no init\n"));
+  return EFI_SUCCESS;
+}
+
diff --git a/Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLibDxe.inf b/Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLibDxe.inf
new file mode 100644
index 0000000..cb2ada6
--- /dev/null
+++ b/Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLibDxe.inf
@@ -0,0 +1,49 @@
+#
+#
+# Copyright (c)  1999  - 2016, Intel Corporation. All rights reserved
+#                                                                                  

+# This program and the accompanying materials are licensed and made available under

+# the terms and conditions of the BSD License that accompanies this distribution.  

+# The full text of the license may be found at                                     

+# http://opensource.org/licenses/bsd-license.php.                                  

+#                                                                                  

+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,            

+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.    

+#                                                                                  

+#
+#
+
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = FlashDeviceLibDxe
+  FILE_GUID                      = F0D7222F-FD43-4A5D-B8BF-A259C87AE3B2
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = FlashDeviceLib | DXE_DRIVER
+  CONSTRUCTOR 				     = LibFvbFlashDeviceSupportInit
+
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64
+#
+
+[Sources]
+  FlashDeviceLib.c
+  FlashDeviceLibDxe.c
+
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  Vlv2TbltDevicePkg/PlatformPkg.dec
+  Vlv2DeviceRefCodePkg/Vlv2DeviceRefCodePkg.dec
+
+[LibraryClasses]
+  DebugLib
+
+[Protocols]
+  gEfiSpiProtocolGuid
+
diff --git a/Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLibDxeRuntimeSmm.c b/Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLibDxeRuntimeSmm.c
new file mode 100644
index 0000000..4e9fc46
--- /dev/null
+++ b/Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLibDxeRuntimeSmm.c
@@ -0,0 +1,188 @@
+/** @file
+
+  Copyright (c) 2004  - 2016, Intel Corporation. All rights reserved.<BR>
+                                                                                   
+
+  This program and the accompanying materials are licensed and made available under
+
+  the terms and conditions of the BSD License that accompanies this distribution.  
+
+  The full text of the license may be found at                                     
+
+  http://opensource.org/licenses/bsd-license.php.                                  
+
+                                                                                   
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,            
+
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.    
+
+                                                                                   
+
+
+
+**/
+
+#include <PiDxe.h>
+
+#include <Library/FlashDeviceLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiRuntimeLib.h>
+#include <Protocol/SmmBase2.h>
+#include <Guid/EventGroup.h>
+#include "SpiChipDefinitions.h"
+
+extern UINTN FlashDeviceBase;
+
+extern EFI_SPI_PROTOCOL *mSpiProtocol;
+
+VOID
+EFIAPI
+LibFvbFlashDeviceVirtualAddressChangeNotifyEvent (
+  IN EFI_EVENT        Event,
+  IN VOID             *Context
+  )
+{
+  gRT->ConvertPointer (0, (VOID **) &mSpiProtocol);
+  gRT->ConvertPointer (0, (VOID **) &FlashDeviceBase);
+}
+
+
+/**
+  The library constructuor.
+
+  The function does the necessary initialization work for this library
+  instance. Please put all initialization works in it.
+
+  @param[in]  ImageHandle       The firmware allocated handle for the UEFI image.
+  @param[in]  SystemTable       A pointer to the EFI system table.
+
+  @retval     EFI_SUCCESS       The function always return EFI_SUCCESS for now.
+                                It will ASSERT on error for debug version.
+  @retval     EFI_ERROR         Please reference LocateProtocol for error code details.
+
+**/
+EFI_STATUS
+EFIAPI
+LibFvbFlashDeviceSupportInit (
+  IN EFI_HANDLE         ImageHandle,
+  IN EFI_SYSTEM_TABLE   *SystemTable
+  )
+{
+  EFI_STATUS Status;
+  EFI_EVENT  Event;
+  UINT8                         SfId[3];
+  UINT8                         FlashIndex;
+  UINT8                         SpiReadError;
+  UINT8                         SpiNotMatchError;
+  EFI_SMM_BASE2_PROTOCOL       *SmmBase;
+  BOOLEAN                       InSmm;
+
+  SpiReadError     = 0x00;
+  SpiNotMatchError = 0x00;
+
+  InSmm = FALSE;
+  Status = gBS->LocateProtocol (
+                  &gEfiSmmBase2ProtocolGuid,
+                  NULL,
+                  (void **)&SmmBase
+                  );
+  if (!EFI_ERROR(Status)) {
+    Status = SmmBase->InSmm(SmmBase, &InSmm);
+    if (EFI_ERROR(Status)) {
+      InSmm = FALSE;
+    }
+  }
+
+  if (!InSmm) {
+    Status = gBS->LocateProtocol (
+                  &gEfiSpiProtocolGuid,
+                  NULL,
+                  (VOID **)&mSpiProtocol
+                  );
+    ASSERT_EFI_ERROR (Status);
+
+    Status = gBS->CreateEventEx (
+                  EVT_NOTIFY_SIGNAL,
+                  TPL_NOTIFY,
+                  LibFvbFlashDeviceVirtualAddressChangeNotifyEvent,
+                  NULL,
+                  &gEfiEventVirtualAddressChangeGuid,
+                  &Event
+                  );
+    ASSERT_EFI_ERROR (Status);
+
+  } else {
+    Status = gBS->LocateProtocol (
+                    &gEfiSmmSpiProtocolGuid,
+                    NULL,
+                    (VOID **)&mSpiProtocol
+                    );
+    ASSERT_EFI_ERROR (Status);
+  }
+
+
+  for (FlashIndex = EnumSpiFlashW25Q64; FlashIndex < EnumSpiFlashMax; FlashIndex++) {
+    Status = mSpiProtocol->Init (mSpiProtocol, &(mInitTable[FlashIndex]));
+    if (!EFI_ERROR (Status)) {
+      //
+      // Read Vendor/Device IDs to check if the driver supports the Serial Flash device.
+      //
+      Status = mSpiProtocol->Execute (
+                               mSpiProtocol,
+                               SPI_READ_ID,
+                               SPI_WREN,
+                               TRUE,
+                               FALSE,
+                               FALSE,
+                               0,
+                               3,
+                               SfId,
+                               EnumSpiRegionAll
+                               );
+      if (!EFI_ERROR (Status)) {
+        if ((SfId[0] == mInitTable[FlashIndex].VendorId)  &&
+            (SfId[1] == mInitTable[FlashIndex].DeviceId0) &&
+            (SfId[2] == mInitTable[FlashIndex].DeviceId1)) {
+            //
+            // Found a matching SPI device, FlashIndex now contains flash device.
+            //
+            DEBUG ((EFI_D_ERROR, "OK - Found SPI Flash Type in SPI Flash Driver, Device Type ID 0 = 0x%02x!\n", mInitTable[FlashIndex].DeviceId0));
+            DEBUG ((EFI_D_ERROR, "Device Type ID 1 = 0x%02x!\n", mInitTable[FlashIndex].DeviceId1));
+
+            if (mInitTable[FlashIndex].BiosStartOffset == (UINTN) (-1)) {
+              DEBUG ((EFI_D_ERROR, "ERROR - The size of BIOS image is bigger than SPI Flash device!\n"));
+              CpuDeadLoop ();
+            }
+            break;
+        } else {
+          SpiNotMatchError++;
+        }
+      } else {
+        SpiReadError++;
+      }
+    }
+  }
+
+  DEBUG ((EFI_D_ERROR, "SPI flash chip VID = 0x%X, DID0 = 0x%X, DID1 = 0x%X\n", SfId[0], SfId[1], SfId[2]));
+
+  if (FlashIndex < EnumSpiFlashMax)  {
+    return EFI_SUCCESS;
+  } else {
+  if (SpiReadError != 0) {
+      DEBUG ((EFI_D_ERROR, "ERROR - SPI Read ID execution failed! Error Count = %d\n", SpiReadError));
+   }
+    else {
+      if (SpiNotMatchError != 0) {
+        DEBUG ((EFI_D_ERROR, "ERROR - No supported SPI flash chip found! Error Count = %d\n", SpiNotMatchError));
+        DEBUG ((EFI_D_ERROR, "SPI flash chip VID = 0x%X, DID0 = 0x%X, DID1 = 0x%X\n", SfId[0], SfId[1], SfId[2]));
+      }
+    }
+    return EFI_UNSUPPORTED;
+  }
+}
+
diff --git a/Vlv2TbltDevicePkg/Library/FlashDeviceLib/SpiChipDefinitions.h b/Vlv2TbltDevicePkg/Library/FlashDeviceLib/SpiChipDefinitions.h
index 15bd1e0..fbde4e6 100644
--- a/Vlv2TbltDevicePkg/Library/FlashDeviceLib/SpiChipDefinitions.h
+++ b/Vlv2TbltDevicePkg/Library/FlashDeviceLib/SpiChipDefinitions.h
@@ -1,6 +1,6 @@
 /*++
 
-  Copyright (c) 2004  - 2014, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2004  - 2016, Intel Corporation. All rights reserved.<BR>
                                                                                    

   This program and the accompanying materials are licensed and made available under

   the terms and conditions of the BSD License that accompanies this distribution.  

@@ -16,8 +16,7 @@
 
 #include <Library/SpiFlash.H>
 
-#define FLASH_SIZE  0x300000
-#define FLASH_DEVICE_BASE_ADDRESS (0xFFFFFFFF-FLASH_SIZE+1)
+#define FLASH_SIZE  0x400000
 
 //
 // Serial Flash device initialization data table provided to the
-- 
2.7.4.windows.1



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

* [PATCH 42/45] Vlv2TbltDevicePkg/PlatformBootManager: Add capsule/recovery handling.
  2016-09-21  6:44 [PATCH 00/45] Add capsule update and recovery sample Jiewen Yao
                   ` (40 preceding siblings ...)
  2016-09-21  6:45 ` [PATCH 41/45] Vlv2TbltDevicePkg/FlashDeviceLib: Add DXE flash device lib Jiewen Yao
@ 2016-09-21  6:45 ` Jiewen Yao
  2016-09-22  2:40   ` Wei, David
  2016-09-21  6:45 ` [PATCH 43/45] Vlv2TbltDevicePkg/dsc/fdf: Add capsule/recovery support Jiewen Yao
                   ` (6 subsequent siblings)
  48 siblings, 1 reply; 83+ messages in thread
From: Jiewen Yao @ 2016-09-21  6:45 UTC (permalink / raw)
  To: edk2-devel
  Cc: David Wei, Feng Tian, Star Zeng, Michael D Kinney, Liming Gao,
	Chao Zhang

Add capsule and recovery boot path handling in platform BDS.

Cc: David Wei <david.wei@intel.com>
Cc: Feng Tian <feng.tian@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Chao Zhang <chao.b.zhang@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
---
 Vlv2TbltDevicePkg/Library/PlatformBdsLib/BdsPlatform.c      | 117 ++++++++++----------
 Vlv2TbltDevicePkg/Library/PlatformBdsLib/PlatformBdsLib.inf |   2 +
 2 files changed, 60 insertions(+), 59 deletions(-)

diff --git a/Vlv2TbltDevicePkg/Library/PlatformBdsLib/BdsPlatform.c b/Vlv2TbltDevicePkg/Library/PlatformBdsLib/BdsPlatform.c
index 02e4616..580d774 100644
--- a/Vlv2TbltDevicePkg/Library/PlatformBdsLib/BdsPlatform.c
+++ b/Vlv2TbltDevicePkg/Library/PlatformBdsLib/BdsPlatform.c
@@ -1,15 +1,15 @@
 /** @file
 
   Copyright (c) 2004  - 2016, Intel Corporation. All rights reserved.<BR>
-                                                                                   

-  This program and the accompanying materials are licensed and made available under

-  the terms and conditions of the BSD License that accompanies this distribution.  

-  The full text of the license may be found at                                     

-  http://opensource.org/licenses/bsd-license.php.                                  

-                                                                                   

-  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,            

-  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.    

-                                                                                   

+                                                                                   
+  This program and the accompanying materials are licensed and made available under
+  the terms and conditions of the BSD License that accompanies this distribution.  
+  The full text of the license may be found at                                     
+  http://opensource.org/licenses/bsd-license.php.                                  
+                                                                                   
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,            
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.    
+                                                                                   
 
 
 Module Name:
@@ -45,6 +45,9 @@ Abstract:
 #include <Library/GenericBdsLib/String.h>
 #include <Library/NetLib.h>
 
+#include <Library/CapsuleLib.h>
+#include <Protocol/EsrtManagement.h>
+
 EFI_GUID *ConnectDriverTable[] = {
   &gEfiMmioDeviceProtocolGuid,
   &gEfiI2cMasterProtocolGuid,
@@ -181,6 +184,11 @@ InstallReadyToLock (
                     );
     ASSERT_EFI_ERROR (Status);
 
+    //
+    // Signal EndOfDxe PI Event
+    //
+    EfiEventGroupSignal (&gEfiEndOfDxeEventGroupGuid);
+
     Handle = NULL;
     Status = gBS->InstallProtocolInterface (
                     &Handle,
@@ -226,11 +234,6 @@ PlatformBdsInit (
   EFI_STATUS  Status;
   EFI_EVENT   ShellImageEvent;
   EFI_GUID    ShellEnvProtocol = SHELL_ENVIRONMENT_INTERFACE_PROTOCOL;
-  
-  //
-  // Signal EndOfDxe PI Event
-  //
-  EfiEventGroupSignal (&gEfiEndOfDxeEventGroupGuid);
 
   #ifdef __GNUC__
   SerialPortWrite((UINT8 *)">>>>BdsEntry[GCC]\r\n", 19);
@@ -1585,7 +1588,7 @@ EFIAPI
 PlatformBdsPolicyBehavior (
   IN OUT LIST_ENTRY                  *DriverOptionList,
   IN OUT LIST_ENTRY                  *BootOptionList,
-  IN PROCESS_CAPSULES                ProcessCapsules,
+  IN PROCESS_CAPSULES                BdsProcessCapsules,
   IN BASEM_MEMORY_TEST               BaseMemoryTest
   )
 {
@@ -1594,11 +1597,8 @@ PlatformBdsPolicyBehavior (
   EFI_BOOT_MODE                      BootMode;
   BOOLEAN                            DeferredImageExist;
   UINTN                              Index;
-  CHAR16                             CapsuleVarName[36];
-  CHAR16                             *TempVarName;
   SYSTEM_CONFIGURATION               SystemConfiguration;
   UINTN                              VarSize;
-  BOOLEAN                            SetVariableFlag;
   PLATFORM_PCI_DEVICE_PATH           *EmmcBootDevPath;
   EFI_GLOBAL_NVS_AREA_PROTOCOL       *GlobalNvsArea;
   EFI_HANDLE                         FvProtocolHandle;
@@ -1612,13 +1612,14 @@ PlatformBdsPolicyBehavior (
   BOOLEAN                            IsFirstBoot;
   UINT16                             *BootOrder;
   UINTN                              BootOrderSize;
+  ESRT_MANAGEMENT_PROTOCOL           *EsrtManagement;
 
   Timeout = PcdGet16 (PcdPlatformBootTimeOut);
   if (Timeout > 10 ) {
     //we think the Timeout variable is corrupted
     Timeout = 10;
   }
-  	
+
   VarSize = sizeof(SYSTEM_CONFIGURATION);
   Status = gRT->GetVariable(
                   NORMAL_SETUP_NAME,
@@ -1639,7 +1640,7 @@ PlatformBdsPolicyBehavior (
               &SystemConfiguration
               );
     ASSERT_EFI_ERROR (Status);
-  }  
+  }
 
   //
   // Load the driver option as the driver option list
@@ -1652,37 +1653,6 @@ PlatformBdsPolicyBehavior (
   BootMode = GetBootModeHob();
 
   //
-  // Clear all the capsule variables CapsuleUpdateData, CapsuleUpdateData1, CapsuleUpdateData2...
-  // as early as possible which will avoid the next time boot after the capsule update
-  // will still into the capsule loop
-  //
-  StrCpy (CapsuleVarName, EFI_CAPSULE_VARIABLE_NAME);
-  TempVarName = CapsuleVarName + StrLen (CapsuleVarName);
-  Index = 0;
-  SetVariableFlag = TRUE;
-  while (SetVariableFlag) {
-    if (Index > 0) {
-      UnicodeValueToString (TempVarName, 0, Index, 0);
-    }
-    Status = gRT->SetVariable (
-                    CapsuleVarName,
-                    &gEfiCapsuleVendorGuid,
-                    EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS |
-                    EFI_VARIABLE_BOOTSERVICE_ACCESS,
-                    0,
-                    (VOID *)NULL
-                    );
-    if (EFI_ERROR (Status)) {
-      //
-      // There is no capsule variables, quit
-      //
-      SetVariableFlag = FALSE;
-      continue;
-    }
-    Index++;
-  }
-
-  //
   // No deferred images exist by default
   //
   DeferredImageExist = FALSE;
@@ -1733,6 +1703,11 @@ PlatformBdsPolicyBehavior (
     }
   }
 
+  Status = gBS->LocateProtocol(&gEsrtManagementProtocolGuid, NULL, (VOID **)&EsrtManagement);
+  if (EFI_ERROR(Status)) {
+    EsrtManagement = NULL;
+  }
+
   switch (BootMode) {
 
   case BOOT_WITH_MINIMAL_CONFIGURATION:
@@ -1822,13 +1797,18 @@ PlatformBdsPolicyBehavior (
     #ifdef FTPM_ENABLE
     TrEEPhysicalPresenceLibProcessRequest(NULL);
     #endif
+
+    if (EsrtManagement != NULL) {
+      EsrtManagement->LockEsrtRepository();
+    }
+
     //
     // Close boot script and install ready to lock
     //
     InstallReadyToLock ();
 
     //
-    // Give one chance to enter the setup if we 
+    // Give one chance to enter the setup if we
     // select Gummiboot "Reboot Into Firmware Interface" and Fast Boot is enabled.
     //
     BootIntoFirmwareInterface();
@@ -1863,6 +1843,10 @@ PlatformBdsPolicyBehavior (
       }
     }
 
+    if (EsrtManagement != NULL) {
+      EsrtManagement->LockEsrtRepository();
+    }
+
     //
     // Close boot script and install ready to lock
     //
@@ -1887,6 +1871,16 @@ PlatformBdsPolicyBehavior (
     //
     PlatformBdsConnectConsole (gPlatformConsole);
     PlatformBdsDiagnostics (EXTENSIVE, FALSE, BaseMemoryTest);
+
+    DEBUG((EFI_D_INFO, "ProcessCapsules Before EndOfDxe......\n"));
+    ProcessCapsules ();
+    DEBUG((EFI_D_INFO, "ProcessCapsules Done\n"));
+
+    //
+    // Close boot script and install ready to lock
+    //
+    InstallReadyToLock ();
+
     BdsLibConnectAll ();
 
     //
@@ -1903,12 +1897,13 @@ PlatformBdsPolicyBehavior (
       }
     }
 
-    //
-    // Close boot script and install ready to lock
-    //
-    InstallReadyToLock ();
+    if (EsrtManagement != NULL) {
+      EsrtManagement->SyncEsrtFmp();
+    }
 
-    ProcessCapsules (BOOT_ON_FLASH_UPDATE);
+    DEBUG((EFI_D_INFO, "ProcessCapsules After ConnectAll......\n"));
+    ProcessCapsules();
+    DEBUG((EFI_D_INFO, "ProcessCapsules Done\n"));
     break;
 
   case BOOT_IN_RECOVERY_MODE:
@@ -2012,6 +2007,10 @@ FULL_CONFIGURATION:
    #ifdef FTPM_ENABLE
    TrEEPhysicalPresenceLibProcessRequest(NULL);
    #endif
+
+    if (EsrtManagement != NULL) {
+      EsrtManagement->SyncEsrtFmp();
+    }
     //
     // Close boot script and install ready to lock
     //
@@ -2029,7 +2028,7 @@ FULL_CONFIGURATION:
     PlatformBdsEnterFrontPageWithHotKey (Timeout, FALSE);
 
 	//
-	// Give one chance to enter the setup if we 
+	// Give one chance to enter the setup if we
 	// select Gummiboot "Reboot Into Firmware Interface"
 	//
 	BootIntoFirmwareInterface();
@@ -2047,7 +2046,7 @@ FULL_CONFIGURATION:
       return;
     }
 
-    
+
     break;
   }
 
diff --git a/Vlv2TbltDevicePkg/Library/PlatformBdsLib/PlatformBdsLib.inf b/Vlv2TbltDevicePkg/Library/PlatformBdsLib/PlatformBdsLib.inf
index c64bab9..ce7c426 100644
--- a/Vlv2TbltDevicePkg/Library/PlatformBdsLib/PlatformBdsLib.inf
+++ b/Vlv2TbltDevicePkg/Library/PlatformBdsLib/PlatformBdsLib.inf
@@ -72,6 +72,7 @@
   FileHandleLib
   S3BootScriptLib
   SerialPortLib
+  CapsuleLib
 
 [Protocols]
   gEfiFirmwareVolume2ProtocolGuid
@@ -90,6 +91,7 @@
   gEfiMmioDeviceProtocolGuid
   gEfiI2cMasterProtocolGuid
   gEfiI2cHostProtocolGuid
+  gEsrtManagementProtocolGuid
 
 [Guids]
   gEfiMemoryTypeInformationGuid
-- 
2.7.4.windows.1



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

* [PATCH 43/45] Vlv2TbltDevicePkg/dsc/fdf: Add capsule/recovery support.
  2016-09-21  6:44 [PATCH 00/45] Add capsule update and recovery sample Jiewen Yao
                   ` (41 preceding siblings ...)
  2016-09-21  6:45 ` [PATCH 42/45] Vlv2TbltDevicePkg/PlatformBootManager: Add capsule/recovery handling Jiewen Yao
@ 2016-09-21  6:45 ` Jiewen Yao
  2016-09-22  1:36   ` Wei, David
  2016-09-22  1:39   ` Wei, David
  2016-09-21  6:45 ` [PATCH 44/45] Vlv2TbltDevicePkg/dsc/fdf: add capsule generation DSC/FDF Jiewen Yao
                   ` (5 subsequent siblings)
  48 siblings, 2 replies; 83+ messages in thread
From: Jiewen Yao @ 2016-09-21  6:45 UTC (permalink / raw)
  To: edk2-devel
  Cc: David Wei, Feng Tian, Star Zeng, Michael D Kinney, Liming Gao,
	Chao Zhang

Add capsule and recovery support module in platform dsc and fdf.

Cc: David Wei <david.wei@intel.com>
Cc: Feng Tian <feng.tian@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Chao Zhang <chao.b.zhang@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
---
 Vlv2TbltDevicePkg/PlatformPkg.fdf       | 132 ++++++++++----------
 Vlv2TbltDevicePkg/PlatformPkgConfig.dsc |   3 +-
 Vlv2TbltDevicePkg/PlatformPkgGcc.fdf    | 132 ++++++++++----------
 Vlv2TbltDevicePkg/PlatformPkgGccX64.dsc |  70 ++++++++++-
 Vlv2TbltDevicePkg/PlatformPkgIA32.dsc   |  70 ++++++++++-
 Vlv2TbltDevicePkg/PlatformPkgX64.dsc    |  70 ++++++++++-
 6 files changed, 341 insertions(+), 136 deletions(-)

diff --git a/Vlv2TbltDevicePkg/PlatformPkg.fdf b/Vlv2TbltDevicePkg/PlatformPkg.fdf
index 93b4d2d..7a793bd 100644
--- a/Vlv2TbltDevicePkg/PlatformPkg.fdf
+++ b/Vlv2TbltDevicePkg/PlatformPkg.fdf
@@ -82,6 +82,9 @@ NumBlocks     = $(FLASH_NUM_BLOCKS)          #The number of blocks in 3Mb FLASH
 SET gPlatformModuleTokenSpaceGuid.PcdFlashAreaBaseAddress            = $(FLASH_AREA_BASE_ADDRESS)
 SET gPlatformModuleTokenSpaceGuid.PcdFlashAreaSize                   = $(FLASH_AREA_SIZE)
 
+SET gUefiCpuPkgTokenSpaceGuid.PcdCpuMicrocodePatchAddress = $(FLASH_REGION_VLVMICROCODE_BASE) + 0x60
+SET gUefiCpuPkgTokenSpaceGuid.PcdCpuMicrocodePatchRegionSize = $(FLASH_REGION_VLVMICROCODE_SIZE) - 0x60
+
 !if $(MINNOW2_FSP_BUILD) == TRUE
 # put below PCD value setting into dsc file
 #SET gFspWrapperTokenSpaceGuid.PcdCpuMicrocodePatchAddress                = $(FLASH_REGION_VLVMICROCODE_BASE)
@@ -242,6 +245,34 @@ FILE RAW = 197DB236-F856-4924-90F8-CDF12FB875F3 {
   $(OUTPUT_DIRECTORY)\$(TARGET)_$(TOOL_CHAIN_TAG)\$(DXE_ARCHITECTURE)\MicrocodeUpdates.bin
 }
 
+!if $(RECOVERY_ENABLE)
+[FV.FVRECOVERY_COMPONENTS]
+FvAlignment        = 16         #FV alignment and FV attributes setting.
+ERASE_POLARITY     = 1
+MEMORY_MAPPED      = TRUE
+STICKY_WRITE       = TRUE
+LOCK_CAP           = TRUE
+LOCK_STATUS        = TRUE
+WRITE_DISABLED_CAP = TRUE
+WRITE_ENABLED_CAP  = TRUE
+WRITE_STATUS       = TRUE
+WRITE_LOCK_CAP     = TRUE
+WRITE_LOCK_STATUS  = TRUE
+READ_DISABLED_CAP  = TRUE
+READ_ENABLED_CAP   = TRUE
+READ_STATUS        = TRUE
+READ_LOCK_CAP      = TRUE
+READ_LOCK_STATUS   = TRUE
+
+INF  RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/PchUsb.inf
+INF  MdeModulePkg/Bus/Pci/EhciPei/EhciPei.inf
+INF  MdeModulePkg/Bus/Usb/UsbBusPei/UsbBusPei.inf
+INF  MdeModulePkg/Bus/Usb/UsbBotPei/UsbBotPei.inf
+INF  FatPkg/FatPei/FatPei.inf
+INF  MdeModulePkg/Universal/Disk/CdExpressPei/CdExpressPei.inf
+INF  MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPei.inf
+!endif
+
 ################################################################################
 #
 # FV Section
@@ -306,6 +337,15 @@ INF MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf
 INF MdeModulePkg/Universal/ReportStatusCodeRouter/Pei/ReportStatusCodeRouterPei.inf
 !endif
 
+!if $(RECOVERY_ENABLE)
+FILE FV_IMAGE = 1E9D7604-EF45-46a0-BD8A-71AC78C17AC1 {
+  SECTION PEI_DEPEX_EXP = {gEfiPeiMemoryDiscoveredPpiGuid AND gEfiPeiBootInRecoveryModePpiGuid}
+  SECTION GUIDED EE4E5898-3914-4259-9D6E-DC7BD79403CF {    # LZMA COMPRESS GUID
+    SECTION FV_IMAGE = FVRECOVERY_COMPONENTS
+  }
+}
+!endif
+
 [FV.FVRECOVERY]
 BlockSize          = $(FLASH_BLOCK_SIZE)
 FvAlignment        = 16         #FV alignment and FV attributes setting.
@@ -373,6 +413,11 @@ INF RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET
 
 INF MdeModulePkg/Universal/PCD/Pei/Pcd.inf
 
+!if $(CAPSULE_ENABLE) || $(RECOVERY_ENABLE)
+  # FMP image decriptor
+INF RuleOverride = FMP_IMAGE_DESC Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptor.inf
+!endif
+
 [FV.FVMAIN]
 BlockSize          = $(FLASH_BLOCK_SIZE)
 FvAlignment        = 16
@@ -717,6 +762,12 @@ FILE FREEFORM = 878AC2CC-5343-46F2-B563-51F89DAF56BA {
   !endif
 !endif
 
+!if $(CAPSULE_ENABLE)
+INF  MdeModulePkg/Universal/EsrtDxe/EsrtDxe.inf
+INF  MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxe.inf
+INF  UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.inf
+!endif
+
 [FV.FVMAIN_COMPACT]
 BlockSize          = $(FLASH_BLOCK_SIZE)
 FvAlignment        = 16
@@ -780,8 +831,8 @@ READ_LOCK_CAP      = TRUE
 READ_LOCK_STATUS   = TRUE
 
 
-[FV.Update_Data]
-BlockSize          = $(FLASH_BLOCK_SIZE)
+!if $(CAPSULE_ENABLE) || $(RECOVERY_ENABLE)
+[FV.CapsuleDispatchFv]
 FvAlignment        = 16
 ERASE_POLARITY     = 1
 MEMORY_MAPPED      = TRUE
@@ -799,71 +850,11 @@ READ_STATUS        = TRUE
 READ_LOCK_CAP      = TRUE
 READ_LOCK_STATUS   = TRUE
 
-FILE RAW = 88888888-8888-8888-8888-888888888888 {
-       FD = Vlv
-     }
-
-[FV.BiosUpdateCargo]
-BlockSize          = $(FLASH_BLOCK_SIZE)
-FvAlignment        = 16
-ERASE_POLARITY     = 1
-MEMORY_MAPPED      = TRUE
-STICKY_WRITE       = TRUE
-LOCK_CAP           = TRUE
-LOCK_STATUS        = TRUE
-WRITE_DISABLED_CAP = TRUE
-WRITE_ENABLED_CAP  = TRUE
-WRITE_STATUS       = TRUE
-WRITE_LOCK_CAP     = TRUE
-WRITE_LOCK_STATUS  = TRUE
-READ_DISABLED_CAP  = TRUE
-READ_ENABLED_CAP   = TRUE
-READ_STATUS        = TRUE
-READ_LOCK_CAP      = TRUE
-READ_LOCK_STATUS   = TRUE
-
-
-
-[FV.BiosUpdate]
-BlockSize          = $(FLASH_BLOCK_SIZE)
-FvAlignment        = 16
-ERASE_POLARITY     = 1
-MEMORY_MAPPED      = TRUE
-STICKY_WRITE       = TRUE
-LOCK_CAP           = TRUE
-LOCK_STATUS        = TRUE
-WRITE_DISABLED_CAP = TRUE
-WRITE_ENABLED_CAP  = TRUE
-WRITE_STATUS       = TRUE
-WRITE_LOCK_CAP     = TRUE
-WRITE_LOCK_STATUS  = TRUE
-READ_DISABLED_CAP  = TRUE
-READ_ENABLED_CAP   = TRUE
-READ_STATUS        = TRUE
-READ_LOCK_CAP      = TRUE
-READ_LOCK_STATUS   = TRUE
-
-[Capsule.Capsule_Boot]
-#
-# gEfiCapsuleGuid supported by platform
-# { 0x3B6686BD, 0x0D76, 0x4030, { 0xB7, 0x0E, 0xB5, 0x51, 0x9E, 0x2F, 0xC5, 0xA0 }}
-#
-CAPSULE_GUID  = 3B6686BD-0D76-4030-B70E-B5519E2FC5A0
-CAPSULE_FLAGS = PersistAcrossReset
-CAPSULE_HEADER_SIZE = 0x20
-
-FV = BiosUpdate
-
-[Capsule.Capsule_Reset]
-#
-# gEfiCapsuleGuid supported by platform
-# { 0x3B6686BD, 0x0D76, 0x4030, { 0xB7, 0x0E, 0xB5, 0x51, 0x9E, 0x2F, 0xC5, 0xA0 }}
-#
-CAPSULE_GUID  = 3B6686BD-0D76-4030-B70E-B5519E2FC5A0
-CAPSULE_FLAGS = PersistAcrossReset
-CAPSULE_HEADER_SIZE = 0x20
+!if $(CAPSULE_ENABLE)
+INF  MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxe.inf
+!endif
 
-FV = BiosUpdate
+!endif
 
 ################################################################################
 #
@@ -1089,3 +1080,12 @@ FV = BiosUpdate
     RAW ASL   Optional            |.aml
   }
 
+[Rule.Common.PEIM.FMP_IMAGE_DESC]
+  FILE PEIM = $(NAMED_GUID) {
+     RAW BIN                  |.acpi
+     PEI_DEPEX PEI_DEPEX Optional        $(INF_OUTPUT)/$(MODULE_NAME).depex
+     PE32      PE32    Align=4K          $(INF_OUTPUT)/$(MODULE_NAME).efi
+     UI       STRING="$(MODULE_NAME)" Optional
+     VERSION  STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+  }
+
diff --git a/Vlv2TbltDevicePkg/PlatformPkgConfig.dsc b/Vlv2TbltDevicePkg/PlatformPkgConfig.dsc
index db50b93..a6af8a1 100644
--- a/Vlv2TbltDevicePkg/PlatformPkgConfig.dsc
+++ b/Vlv2TbltDevicePkg/PlatformPkgConfig.dsc
@@ -1,7 +1,7 @@
 #/** @file
 # platform configuration file.
 #
-# Copyright (c) 2012  - 2015, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2012  - 2016, Intel Corporation. All rights reserved.<BR>
 #                                                                                  

 # This program and the accompanying materials are licensed and made available under

 # the terms and conditions of the BSD License that accompanies this distribution.  

@@ -65,6 +65,7 @@ DEFINE VARIABLE_INFO_ENABLE = FALSE
 DEFINE S3_ENABLE = TRUE
 DEFINE CAPSULE_ENABLE = FALSE
 DEFINE CAPSULE_RESET_ENABLE = TRUE
+DEFINE RECOVERY_ENABLE = FALSE
 
 DEFINE GOP_DRIVER_ENABLE = TRUE
 DEFINE DATAHUB_ENABLE = TRUE
diff --git a/Vlv2TbltDevicePkg/PlatformPkgGcc.fdf b/Vlv2TbltDevicePkg/PlatformPkgGcc.fdf
index 33f2038..4dfc09d 100644
--- a/Vlv2TbltDevicePkg/PlatformPkgGcc.fdf
+++ b/Vlv2TbltDevicePkg/PlatformPkgGcc.fdf
@@ -82,6 +82,9 @@ NumBlocks     = $(FLASH_NUM_BLOCKS)          #The number of blocks in 3Mb FLASH
 SET gPlatformModuleTokenSpaceGuid.PcdFlashAreaBaseAddress            = $(FLASH_AREA_BASE_ADDRESS)
 SET gPlatformModuleTokenSpaceGuid.PcdFlashAreaSize                   = $(FLASH_AREA_SIZE)
 
+SET gUefiCpuPkgTokenSpaceGuid.PcdCpuMicrocodePatchAddress = $(FLASH_REGION_VLVMICROCODE_BASE) + 0x60
+SET gUefiCpuPkgTokenSpaceGuid.PcdCpuMicrocodePatchRegionSize = $(FLASH_REGION_VLVMICROCODE_SIZE) - 0x60
+
 !if $(MINNOW2_FSP_BUILD) == TRUE
 # put below PCD value setting into dsc file
 #SET gFspWrapperTokenSpaceGuid.PcdCpuMicrocodePatchAddress                = $(FLASH_REGION_VLVMICROCODE_BASE)
@@ -199,6 +202,34 @@ FILE RAW = 197DB236-F856-4924-90F8-CDF12FB875F3 {
   $(OUTPUT_DIRECTORY)/$(TARGET)_$(TOOL_CHAIN_TAG)/$(DXE_ARCHITECTURE)/MicrocodeUpdates.bin
 }
 
+!if $(RECOVERY_ENABLE) == TRUE
+[FV.FVRECOVERY_COMPONENTS]
+FvAlignment        = 16         #FV alignment and FV attributes setting.
+ERASE_POLARITY     = 1
+MEMORY_MAPPED      = TRUE
+STICKY_WRITE       = TRUE
+LOCK_CAP           = TRUE
+LOCK_STATUS        = TRUE
+WRITE_DISABLED_CAP = TRUE
+WRITE_ENABLED_CAP  = TRUE
+WRITE_STATUS       = TRUE
+WRITE_LOCK_CAP     = TRUE
+WRITE_LOCK_STATUS  = TRUE
+READ_DISABLED_CAP  = TRUE
+READ_ENABLED_CAP   = TRUE
+READ_STATUS        = TRUE
+READ_LOCK_CAP      = TRUE
+READ_LOCK_STATUS   = TRUE
+
+INF  RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/PchUsb.inf
+INF  MdeModulePkg/Bus/Pci/EhciPei/EhciPei.inf
+INF  MdeModulePkg/Bus/Usb/UsbBusPei/UsbBusPei.inf
+INF  MdeModulePkg/Bus/Usb/UsbBotPei/UsbBotPei.inf
+INF  FatPkg/FatPei/FatPei.inf
+INF  MdeModulePkg/Universal/Disk/CdExpressPei/CdExpressPei.inf
+INF  MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPei.inf
+!endif
+
 ################################################################################
 #
 # FV Section
@@ -263,6 +294,15 @@ INF MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf
 INF MdeModulePkg/Universal/ReportStatusCodeRouter/Pei/ReportStatusCodeRouterPei.inf
 !endif
 
+!if $(RECOVERY_ENABLE)
+FILE FV_IMAGE = 1E9D7604-EF45-46a0-BD8A-71AC78C17AC1 {
+  SECTION PEI_DEPEX_EXP = {gEfiPeiMemoryDiscoveredPpiGuid AND gEfiPeiBootInRecoveryModePpiGuid}
+  SECTION GUIDED EE4E5898-3914-4259-9D6E-DC7BD79403CF {    # LZMA COMPRESS GUID
+    SECTION FV_IMAGE = FVRECOVERY_COMPONENTS
+  }
+}
+!endif
+
 [FV.FVRECOVERY]
 BlockSize          = $(FLASH_BLOCK_SIZE)
 FvAlignment        = 16         #FV alignment and FV attributes setting.
@@ -330,6 +370,11 @@ INF RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET
 
 INF MdeModulePkg/Universal/PCD/Pei/Pcd.inf
 
+!if $(CAPSULE_ENABLE) || $(RECOVERY_ENABLE)
+  # FMP image decriptor
+INF RuleOverride = FMP_IMAGE_DESC Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptor.inf
+!endif
+
 [FV.FVMAIN]
 BlockSize          = $(FLASH_BLOCK_SIZE)
 FvAlignment        = 16
@@ -674,6 +719,12 @@ FILE FREEFORM = 878AC2CC-5343-46F2-B563-51F89DAF56BA {
   !endif
 !endif
 
+!if $(CAPSULE_ENABLE)
+INF  MdeModulePkg/Universal/EsrtDxe/EsrtDxe.inf
+INF  MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxe.inf
+INF  UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.inf
+!endif
+
 [FV.FVMAIN_COMPACT]
 BlockSize          = $(FLASH_BLOCK_SIZE)
 FvAlignment        = 16
@@ -737,8 +788,8 @@ READ_LOCK_CAP      = TRUE
 READ_LOCK_STATUS   = TRUE
 
 
-[FV.Update_Data]
-BlockSize          = $(FLASH_BLOCK_SIZE)
+!if $(CAPSULE_ENABLE) || $(RECOVERY_ENABLE)
+[FV.CapsuleDispatchFv]
 FvAlignment        = 16
 ERASE_POLARITY     = 1
 MEMORY_MAPPED      = TRUE
@@ -756,71 +807,11 @@ READ_STATUS        = TRUE
 READ_LOCK_CAP      = TRUE
 READ_LOCK_STATUS   = TRUE
 
-FILE RAW = 88888888-8888-8888-8888-888888888888 {
-       FD = Vlv
-     }
-
-[FV.BiosUpdateCargo]
-BlockSize          = $(FLASH_BLOCK_SIZE)
-FvAlignment        = 16
-ERASE_POLARITY     = 1
-MEMORY_MAPPED      = TRUE
-STICKY_WRITE       = TRUE
-LOCK_CAP           = TRUE
-LOCK_STATUS        = TRUE
-WRITE_DISABLED_CAP = TRUE
-WRITE_ENABLED_CAP  = TRUE
-WRITE_STATUS       = TRUE
-WRITE_LOCK_CAP     = TRUE
-WRITE_LOCK_STATUS  = TRUE
-READ_DISABLED_CAP  = TRUE
-READ_ENABLED_CAP   = TRUE
-READ_STATUS        = TRUE
-READ_LOCK_CAP      = TRUE
-READ_LOCK_STATUS   = TRUE
-
-
-
-[FV.BiosUpdate]
-BlockSize          = $(FLASH_BLOCK_SIZE)
-FvAlignment        = 16
-ERASE_POLARITY     = 1
-MEMORY_MAPPED      = TRUE
-STICKY_WRITE       = TRUE
-LOCK_CAP           = TRUE
-LOCK_STATUS        = TRUE
-WRITE_DISABLED_CAP = TRUE
-WRITE_ENABLED_CAP  = TRUE
-WRITE_STATUS       = TRUE
-WRITE_LOCK_CAP     = TRUE
-WRITE_LOCK_STATUS  = TRUE
-READ_DISABLED_CAP  = TRUE
-READ_ENABLED_CAP   = TRUE
-READ_STATUS        = TRUE
-READ_LOCK_CAP      = TRUE
-READ_LOCK_STATUS   = TRUE
-
-[Capsule.Capsule_Boot]
-#
-# gEfiCapsuleGuid supported by platform
-# { 0x3B6686BD, 0x0D76, 0x4030, { 0xB7, 0x0E, 0xB5, 0x51, 0x9E, 0x2F, 0xC5, 0xA0 }}
-#
-CAPSULE_GUID  = 3B6686BD-0D76-4030-B70E-B5519E2FC5A0
-CAPSULE_FLAGS = PersistAcrossReset
-CAPSULE_HEADER_SIZE = 0x20
-
-FV = BiosUpdate
-
-[Capsule.Capsule_Reset]
-#
-# gEfiCapsuleGuid supported by platform
-# { 0x3B6686BD, 0x0D76, 0x4030, { 0xB7, 0x0E, 0xB5, 0x51, 0x9E, 0x2F, 0xC5, 0xA0 }}
-#
-CAPSULE_GUID  = 3B6686BD-0D76-4030-B70E-B5519E2FC5A0
-CAPSULE_FLAGS = PersistAcrossReset
-CAPSULE_HEADER_SIZE = 0x20
+!if $(CAPSULE_ENABLE)
+INF  MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxe.inf
+!endif
 
-FV = BiosUpdate
+!endif
 
 ################################################################################
 #
@@ -1050,3 +1041,12 @@ FV = BiosUpdate
     RAW ASL   Optional            |.aml
   }
 
+[Rule.Common.PEIM.FMP_IMAGE_DESC]
+  FILE PEIM = $(NAMED_GUID) {
+     RAW BIN                  |.acpi
+     PEI_DEPEX PEI_DEPEX Optional        $(INF_OUTPUT)/$(MODULE_NAME).depex
+     PE32      PE32    Align=4K          $(INF_OUTPUT)/$(MODULE_NAME).efi
+     UI       STRING="$(MODULE_NAME)" Optional
+     VERSION  STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+  }
+
diff --git a/Vlv2TbltDevicePkg/PlatformPkgGccX64.dsc b/Vlv2TbltDevicePkg/PlatformPkgGccX64.dsc
index 7125366..47bb23e 100644
--- a/Vlv2TbltDevicePkg/PlatformPkgGccX64.dsc
+++ b/Vlv2TbltDevicePkg/PlatformPkgGccX64.dsc
@@ -183,10 +183,15 @@
 
   OemHookStatusCodeLib|MdeModulePkg/Library/OemHookStatusCodeLibNull/OemHookStatusCodeLibNull.inf
 !if $(CAPSULE_ENABLE) == TRUE
- CapsuleLib|IntelFrameworkModulePkg/Library/DxeCapsuleLib/DxeCapsuleLib.inf
+  CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.inf
 !else
   CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf
 !endif
+  EdkiiSystemCapsuleLib|MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.inf
+  FmpAuthenticationLib|MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.inf
+  IniParsingLib|MdeModulePkg/Library/IniParsingLib/IniParsingLib.inf
+  PlatformFlashAccessLib|Vlv2TbltDevicePkg/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.inf
+  MicrocodeFlashAccessLib|Vlv2TbltDevicePkg/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.inf
   LanguageLib|EdkCompatibilityPkg/Compatibility/Library/UefiLanguageLib/UefiLanguageLib.inf
   SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
   SecurityManagementLib|MdeModulePkg/Library/DxeSecurityManagementLib/DxeSecurityManagementLib.inf
@@ -381,6 +386,8 @@
   DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgentLib.inf
 !endif
 
+  FlashDeviceLib|$(PLATFORM_PACKAGE)/Library/FlashDeviceLib/FlashDeviceLibDxe.inf
+
 [LibraryClasses.X64.DXE_CORE]
   HobLib|MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.inf
   MemoryAllocationLib|MdeModulePkg/Library/DxeCoreMemoryAllocationLib/DxeCoreMemoryAllocationLib.inf
@@ -450,6 +457,10 @@
   DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgentLib.inf
 !endif
 
+!if $(CAPSULE_ENABLE)
+  CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf
+!endif
+
 [LibraryClasses.common.UEFI_DRIVER]
   PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
 
@@ -886,6 +897,11 @@
   gEfiVLVTokenSpaceGuid.PcdCpuSmramCpuDataAddress|0
   gEfiVLVTokenSpaceGuid.PcdCpuLockBoxSize|0
 
+!if $(CAPSULE_ENABLE) || $(RECOVERY_ENABLE)
+  gEfiMdeModulePkgTokenSpaceGuid.PcdEdkiiSystemFmpCapsuleImageTypeIdGuid|{0x7b, 0x26, 0x96, 0x40, 0x0a, 0xda, 0xeb, 0x42, 0xb5, 0xeb, 0xfe, 0xf3, 0x1d, 0x20, 0x7c, 0xb4}
+  gEfiMdeModulePkgTokenSpaceGuid.PcdEdkiiSystemFirmwareImageDescriptor|{0x0}|VOID*|0x100
+!endif
+
 [Components.IA32]
 
   $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/SecCore.inf
@@ -907,6 +923,14 @@
   }
   !endif
 
+!if $(CAPSULE_ENABLE) || $(RECOVERY_ENABLE)
+  # FMP image decriptor
+  Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptor.inf {
+    <LibraryClasses>
+      PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf
+  }
+!endif
+
   MdeModulePkg/Core/Pei/PeiMain.inf {
 !if $(TARGET) == DEBUG
     <PcdsFixedAtBuild>
@@ -1011,6 +1035,24 @@ $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/fTPMInitPeim.inf
   $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/MpS3.inf
   EdkCompatibilityPkg/Compatibility/AcpiVariableHobOnSmramReserveHobThunk/AcpiVariableHobOnSmramReserveHobThunk.inf
   $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/PiSmmCommunicationPei.inf
+
+!if $(RECOVERY_ENABLE)
+  #
+  # Recovery
+  #
+  $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/PchUsb.inf
+  MdeModulePkg/Bus/Pci/EhciPei/EhciPei.inf
+  MdeModulePkg/Bus/Usb/UsbBusPei/UsbBusPei.inf
+  MdeModulePkg/Bus/Usb/UsbBotPei/UsbBotPei.inf
+  FatPkg/FatPei/FatPei.inf
+  MdeModulePkg/Universal/Disk/CdExpressPei/CdExpressPei.inf
+  MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPei.inf {
+    <LibraryClasses>
+      NULL|SecurityPkg/Library/FmpAuthenticationRsa2048Sha256Lib/FmpAuthenticationRsa2048Sha256Lib.inf
+      PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf
+  }
+!endif
+
 !if $(CAPSULE_ENABLE) == TRUE
   MdeModulePkg/Universal/CapsulePei/CapsulePei.inf
 !endif
@@ -1146,6 +1188,9 @@ $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/fTPMInitPeim.inf
       DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
       PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
       SerialPortLib|$(PLATFORM_PACKAGE)/Library/SerialPortLib/SerialPortLib.inf
+!if $(CAPSULE_ENABLE) == TRUE
+      NULL|SecurityPkg/Library/FmpAuthenticationPkcs7Lib/FmpAuthenticationPkcs7Lib.inf
+!endif
     !if $(FTPM_ENABLE) == TRUE
       Tpm2DeviceLib|Vlv2TbltDevicePkg/Library/Tpm2DeviceLibSeCDxe/Tpm2DeviceLibSeC.inf
     !else
@@ -1518,6 +1563,29 @@ $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/fTPMInitPeim.inf
 
   Vlv2TbltDevicePkg/Application/FirmwareUpdate/FirmwareUpdate.inf
 
+!if $(CAPSULE_ENABLE)
+  MdeModulePkg/Universal/EsrtDxe/EsrtDxe.inf
+
+  MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxe.inf
+  MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxe.inf {
+    <LibraryClasses>
+      DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
+      PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
+      SerialPortLib|$(PLATFORM_PACKAGE)/Library/SerialPortLib/SerialPortLib.inf
+      NULL|SecurityPkg/Library/FmpAuthenticationPkcs7Lib/FmpAuthenticationPkcs7Lib.inf
+  }
+  MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf
+
+  UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.inf {
+    <LibraryClasses>
+      DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
+      PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
+      SerialPortLib|$(PLATFORM_PACKAGE)/Library/SerialPortLib/SerialPortLib.inf
+  }
+  UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.inf
+
+!endif
+
 [BuildOptions]
 #
 # Define Build Options both for EDK and EDKII drivers.
diff --git a/Vlv2TbltDevicePkg/PlatformPkgIA32.dsc b/Vlv2TbltDevicePkg/PlatformPkgIA32.dsc
index 6efaf32..5f46793 100644
--- a/Vlv2TbltDevicePkg/PlatformPkgIA32.dsc
+++ b/Vlv2TbltDevicePkg/PlatformPkgIA32.dsc
@@ -183,10 +183,15 @@
 
   OemHookStatusCodeLib|MdeModulePkg/Library/OemHookStatusCodeLibNull/OemHookStatusCodeLibNull.inf
 !if $(CAPSULE_ENABLE) == TRUE
- CapsuleLib|IntelFrameworkModulePkg/Library/DxeCapsuleLib/DxeCapsuleLib.inf
+  CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.inf
 !else
   CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf
 !endif
+  EdkiiSystemCapsuleLib|MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.inf
+  FmpAuthenticationLib|MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.inf
+  IniParsingLib|MdeModulePkg/Library/IniParsingLib/IniParsingLib.inf
+  PlatformFlashAccessLib|Vlv2TbltDevicePkg/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.inf
+  MicrocodeFlashAccessLib|Vlv2TbltDevicePkg/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.inf
   LanguageLib|EdkCompatibilityPkg/Compatibility/Library/UefiLanguageLib/UefiLanguageLib.inf
   SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
   SecurityManagementLib|MdeModulePkg/Library/DxeSecurityManagementLib/DxeSecurityManagementLib.inf
@@ -381,6 +386,8 @@
   DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgentLib.inf
 !endif
 
+  FlashDeviceLib|$(PLATFORM_PACKAGE)/Library/FlashDeviceLib/FlashDeviceLibDxe.inf
+
 [LibraryClasses.IA32.DXE_CORE]
   HobLib|MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.inf
   MemoryAllocationLib|MdeModulePkg/Library/DxeCoreMemoryAllocationLib/DxeCoreMemoryAllocationLib.inf
@@ -450,6 +457,10 @@
   DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgentLib.inf
 !endif
 
+!if $(CAPSULE_ENABLE) == TRUE
+  CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf
+!endif
+
 [LibraryClasses.common.UEFI_DRIVER]
   PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
 
@@ -888,6 +899,11 @@
   gEfiVLVTokenSpaceGuid.PcdCpuSmramCpuDataAddress|0
   gEfiVLVTokenSpaceGuid.PcdCpuLockBoxSize|0
 
+!if $(CAPSULE_ENABLE) || $(RECOVERY_ENABLE)
+  gEfiMdeModulePkgTokenSpaceGuid.PcdEdkiiSystemFmpCapsuleImageTypeIdGuid|{0x7b, 0x26, 0x96, 0x40, 0x0a, 0xda, 0xeb, 0x42, 0xb5, 0xeb, 0xfe, 0xf3, 0x1d, 0x20, 0x7c, 0xb4}
+  gEfiMdeModulePkgTokenSpaceGuid.PcdEdkiiSystemFirmwareImageDescriptor|{0x0}|VOID*|0x100
+!endif
+
 [Components.IA32]
 
   $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/SecCore.inf
@@ -909,6 +925,14 @@
   }
   !endif
 
+!if $(CAPSULE_ENABLE) || $(RECOVERY_ENABLE)
+  # FMP image decriptor
+  Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptor.inf {
+    <LibraryClasses>
+      PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf
+  }
+!endif
+
   MdeModulePkg/Core/Pei/PeiMain.inf {
 !if $(TARGET) == DEBUG
     <PcdsFixedAtBuild>
@@ -1008,6 +1032,24 @@ $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/fTPMInitPeim.inf
   $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/MpS3.inf
   EdkCompatibilityPkg/Compatibility/AcpiVariableHobOnSmramReserveHobThunk/AcpiVariableHobOnSmramReserveHobThunk.inf
   $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/PiSmmCommunicationPei.inf
+
+!if $(RECOVERY_ENABLE)
+  #
+  # Recovery
+  #
+  $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/PchUsb.inf
+  MdeModulePkg/Bus/Pci/EhciPei/EhciPei.inf
+  MdeModulePkg/Bus/Usb/UsbBusPei/UsbBusPei.inf
+  MdeModulePkg/Bus/Usb/UsbBotPei/UsbBotPei.inf
+  FatPkg/FatPei/FatPei.inf
+  MdeModulePkg/Universal/Disk/CdExpressPei/CdExpressPei.inf
+  MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPei.inf {
+    <LibraryClasses>
+      NULL|SecurityPkg/Library/FmpAuthenticationRsa2048Sha256Lib/FmpAuthenticationRsa2048Sha256Lib.inf
+      PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf
+  }
+!endif
+
 !if $(CAPSULE_ENABLE) == TRUE
   MdeModulePkg/Universal/CapsulePei/CapsulePei.inf
 !endif
@@ -1133,6 +1175,9 @@ $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/fTPMInitPeim.inf
       DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
       PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
       SerialPortLib|$(PLATFORM_PACKAGE)/Library/SerialPortLib/SerialPortLib.inf
+!if $(CAPSULE_ENABLE)
+      NULL|SecurityPkg/Library/FmpAuthenticationPkcs7Lib/FmpAuthenticationPkcs7Lib.inf
+!endif
     !if $(FTPM_ENABLE) == TRUE
       Tpm2DeviceLib|Vlv2TbltDevicePkg/Library/Tpm2DeviceLibSeCDxe/Tpm2DeviceLibSeC.inf
     !else
@@ -1499,6 +1544,29 @@ $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/fTPMInitPeim.inf
 
   Vlv2TbltDevicePkg/Application/FirmwareUpdate/FirmwareUpdate.inf
 
+!if $(CAPSULE_ENABLE)
+  MdeModulePkg/Universal/EsrtDxe/EsrtDxe.inf
+
+  MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxe.inf
+  MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxe.inf {
+    <LibraryClasses>
+      DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
+      PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
+      SerialPortLib|$(PLATFORM_PACKAGE)/Library/SerialPortLib/SerialPortLib.inf
+      NULL|SecurityPkg/Library/FmpAuthenticationPkcs7Lib/FmpAuthenticationPkcs7Lib.inf
+  }
+  MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf
+
+  UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.inf {
+    <LibraryClasses>
+      DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
+      PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
+      SerialPortLib|$(PLATFORM_PACKAGE)/Library/SerialPortLib/SerialPortLib.inf
+  }
+  UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.inf
+
+!endif
+
 [BuildOptions]
 #
 # Define Build Options both for EDK and EDKII drivers.
diff --git a/Vlv2TbltDevicePkg/PlatformPkgX64.dsc b/Vlv2TbltDevicePkg/PlatformPkgX64.dsc
index 6bb503d..b2ac048 100644
--- a/Vlv2TbltDevicePkg/PlatformPkgX64.dsc
+++ b/Vlv2TbltDevicePkg/PlatformPkgX64.dsc
@@ -183,10 +183,15 @@
 
   OemHookStatusCodeLib|MdeModulePkg/Library/OemHookStatusCodeLibNull/OemHookStatusCodeLibNull.inf
 !if $(CAPSULE_ENABLE) == TRUE
- CapsuleLib|IntelFrameworkModulePkg/Library/DxeCapsuleLib/DxeCapsuleLib.inf
+  CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.inf
 !else
   CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf
 !endif
+  EdkiiSystemCapsuleLib|MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.inf
+  FmpAuthenticationLib|MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.inf
+  IniParsingLib|MdeModulePkg/Library/IniParsingLib/IniParsingLib.inf
+  PlatformFlashAccessLib|Vlv2TbltDevicePkg/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.inf
+  MicrocodeFlashAccessLib|Vlv2TbltDevicePkg/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.inf
   LanguageLib|EdkCompatibilityPkg/Compatibility/Library/UefiLanguageLib/UefiLanguageLib.inf
   SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
   SecurityManagementLib|MdeModulePkg/Library/DxeSecurityManagementLib/DxeSecurityManagementLib.inf
@@ -381,6 +386,8 @@
   DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgentLib.inf
 !endif
 
+  FlashDeviceLib|$(PLATFORM_PACKAGE)/Library/FlashDeviceLib/FlashDeviceLibDxe.inf
+
 [LibraryClasses.X64.DXE_CORE]
   HobLib|MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.inf
   MemoryAllocationLib|MdeModulePkg/Library/DxeCoreMemoryAllocationLib/DxeCoreMemoryAllocationLib.inf
@@ -450,6 +457,10 @@
   DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgentLib.inf
 !endif
 
+!if $(CAPSULE_ENABLE)
+  CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf
+!endif
+
 [LibraryClasses.common.UEFI_DRIVER]
   PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
 
@@ -885,6 +896,11 @@
   gEfiVLVTokenSpaceGuid.PcdCpuSmramCpuDataAddress|0
   gEfiVLVTokenSpaceGuid.PcdCpuLockBoxSize|0
 
+!if $(CAPSULE_ENABLE) || $(RECOVERY_ENABLE)
+  gEfiMdeModulePkgTokenSpaceGuid.PcdEdkiiSystemFmpCapsuleImageTypeIdGuid|{0x7b, 0x26, 0x96, 0x40, 0x0a, 0xda, 0xeb, 0x42, 0xb5, 0xeb, 0xfe, 0xf3, 0x1d, 0x20, 0x7c, 0xb4}
+  gEfiMdeModulePkgTokenSpaceGuid.PcdEdkiiSystemFirmwareImageDescriptor|{0x0}|VOID*|0x100
+!endif
+
 [Components.IA32]
 
   $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/SecCore.inf
@@ -906,6 +922,14 @@
   }
   !endif
 
+!if $(CAPSULE_ENABLE) || $(RECOVERY_ENABLE)
+  # FMP image decriptor
+  Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptor.inf {
+    <LibraryClasses>
+      PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf
+  }
+!endif
+
   MdeModulePkg/Core/Pei/PeiMain.inf {
 !if $(TARGET) == DEBUG
     <PcdsFixedAtBuild>
@@ -1005,6 +1029,24 @@ $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/fTPMInitPeim.inf
   $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/MpS3.inf
   EdkCompatibilityPkg/Compatibility/AcpiVariableHobOnSmramReserveHobThunk/AcpiVariableHobOnSmramReserveHobThunk.inf
   $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/PiSmmCommunicationPei.inf
+
+!if $(RECOVERY_ENABLE)
+  #
+  # Recovery
+  #
+  $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/PchUsb.inf
+  MdeModulePkg/Bus/Pci/EhciPei/EhciPei.inf
+  MdeModulePkg/Bus/Usb/UsbBusPei/UsbBusPei.inf
+  MdeModulePkg/Bus/Usb/UsbBotPei/UsbBotPei.inf
+  FatPkg/FatPei/FatPei.inf
+  MdeModulePkg/Universal/Disk/CdExpressPei/CdExpressPei.inf
+  MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPei.inf {
+    <LibraryClasses>
+      NULL|SecurityPkg/Library/FmpAuthenticationRsa2048Sha256Lib/FmpAuthenticationRsa2048Sha256Lib.inf
+      PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf
+  }
+!endif
+
 !if $(CAPSULE_ENABLE) == TRUE
   MdeModulePkg/Universal/CapsulePei/CapsulePei.inf
 !endif
@@ -1139,6 +1181,9 @@ $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/fTPMInitPeim.inf
       DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
       PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
       SerialPortLib|$(PLATFORM_PACKAGE)/Library/SerialPortLib/SerialPortLib.inf
+!if $(CAPSULE_ENABLE)
+      NULL|SecurityPkg/Library/FmpAuthenticationPkcs7Lib/FmpAuthenticationPkcs7Lib.inf
+!endif
     !if $(FTPM_ENABLE) == TRUE
       Tpm2DeviceLib|Vlv2TbltDevicePkg/Library/Tpm2DeviceLibSeCDxe/Tpm2DeviceLibSeC.inf
     !else
@@ -1505,6 +1550,29 @@ $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/fTPMInitPeim.inf
 
   Vlv2TbltDevicePkg/Application/FirmwareUpdate/FirmwareUpdate.inf
 
+!if $(CAPSULE_ENABLE)
+  MdeModulePkg/Universal/EsrtDxe/EsrtDxe.inf
+
+  MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxe.inf
+  MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxe.inf {
+    <LibraryClasses>
+      DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
+      PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
+      SerialPortLib|$(PLATFORM_PACKAGE)/Library/SerialPortLib/SerialPortLib.inf
+      NULL|SecurityPkg/Library/FmpAuthenticationPkcs7Lib/FmpAuthenticationPkcs7Lib.inf
+  }
+  MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf
+
+  UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.inf {
+    <LibraryClasses>
+      DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
+      PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
+      SerialPortLib|$(PLATFORM_PACKAGE)/Library/SerialPortLib/SerialPortLib.inf
+  }
+  UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.inf
+
+!endif
+
 [BuildOptions]
 #
 # Define Build Options both for EDK and EDKII drivers.
-- 
2.7.4.windows.1



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

* [PATCH 44/45] Vlv2TbltDevicePkg/dsc/fdf: add capsule generation DSC/FDF.
  2016-09-21  6:44 [PATCH 00/45] Add capsule update and recovery sample Jiewen Yao
                   ` (42 preceding siblings ...)
  2016-09-21  6:45 ` [PATCH 43/45] Vlv2TbltDevicePkg/dsc/fdf: Add capsule/recovery support Jiewen Yao
@ 2016-09-21  6:45 ` Jiewen Yao
  2016-09-21  6:45 ` [PATCH 45/45] Vlv2TbltDevicePkg/bat: add capsule generation in bat Jiewen Yao
                   ` (4 subsequent siblings)
  48 siblings, 0 replies; 83+ messages in thread
From: Jiewen Yao @ 2016-09-21  6:45 UTC (permalink / raw)
  To: edk2-devel
  Cc: David Wei, Feng Tian, Star Zeng, Michael D Kinney, Liming Gao,
	Chao Zhang

Add DSC/FDF to generate capsule image.
It is separated from normal DSC/FDF, because the FDF file need use
the result of final build.

Cc: David Wei <david.wei@intel.com>
Cc: Feng Tian <feng.tian@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Chao Zhang <chao.b.zhang@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
---
 Vlv2TbltDevicePkg/PlatformCapsule.dsc    | 44 +++++++++++
 Vlv2TbltDevicePkg/PlatformCapsule.fdf    | 81 ++++++++++++++++++++
 Vlv2TbltDevicePkg/PlatformCapsuleGcc.fdf | 81 ++++++++++++++++++++
 3 files changed, 206 insertions(+)

diff --git a/Vlv2TbltDevicePkg/PlatformCapsule.dsc b/Vlv2TbltDevicePkg/PlatformCapsule.dsc
new file mode 100644
index 0000000..a619ed8
--- /dev/null
+++ b/Vlv2TbltDevicePkg/PlatformCapsule.dsc
@@ -0,0 +1,44 @@
+#/** @file
+# Platform capsule description.
+#
+# Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License that accompanies this distribution.
+# The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php.
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#
+#**/
+
+[Defines]
+  PLATFORM_NAME                  = Vlv2TbltDevicePkg
+  PLATFORM_GUID                  = EE87F258-6ECC-4415-B1D8-23771BEE26E7
+  PLATFORM_VERSION               = 0.1
+  FLASH_DEFINITION               = Vlv2TbltDevicePkg/PlatformCapsule.fdf
+  OUTPUT_DIRECTORY               = Build/Vlv2TbltDevicePkg
+  SUPPORTED_ARCHITECTURES        = IA32|X64
+  BUILD_TARGETS                  = DEBUG|RELEASE
+  SKUID_IDENTIFIER               = DEFAULT
+
+###################################################################################################
+#
+# Components Section - list of the modules and components that will be processed by compilation
+#                      tools and the EDK II tools to generate PE32/PE32+/Coff image files.
+#
+# Note: The EDK II DSC file is not used to specify how compiled binary images get placed
+#       into firmware volume images. This section is just a list of modules to compile from
+#       source into UEFI-compliant binaries.
+#       It is the FDF file that contains information on combining binary files into firmware
+#       volume images, whose concept is beyond UEFI and is described in PI specification.
+#       Binary modules do not need to be listed in this section, as they should be
+#       specified in the FDF file. For example: Shell binary, FAT binary (Fat.efi),
+#       Logo (Logo.bmp), and etc.
+#       There may also be modules listed in this section that are not required in the FDF file,
+#       When a module listed here is excluded from FDF file, then UEFI-compliant binary will be
+#       generated for it, but the binary will not be put into any firmware volume.
+#
+###################################################################################################
diff --git a/Vlv2TbltDevicePkg/PlatformCapsule.fdf b/Vlv2TbltDevicePkg/PlatformCapsule.fdf
new file mode 100644
index 0000000..d51a0ec
--- /dev/null
+++ b/Vlv2TbltDevicePkg/PlatformCapsule.fdf
@@ -0,0 +1,81 @@
+## @file
+# FDF file of Platform capsule.
+#
+# Copyright (c) 2016 Intel Corporation.
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution.  The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[FV.BiosUpdateCargo]
+FvAlignment        = 16
+ERASE_POLARITY     = 1
+MEMORY_MAPPED      = TRUE
+STICKY_WRITE       = TRUE
+LOCK_CAP           = TRUE
+LOCK_STATUS        = TRUE
+WRITE_DISABLED_CAP = TRUE
+WRITE_ENABLED_CAP  = TRUE
+WRITE_STATUS       = TRUE
+WRITE_LOCK_CAP     = TRUE
+WRITE_LOCK_STATUS  = TRUE
+READ_DISABLED_CAP  = TRUE
+READ_ENABLED_CAP   = TRUE
+READ_STATUS        = TRUE
+READ_LOCK_CAP      = TRUE
+READ_LOCK_STATUS   = TRUE
+
+FILE RAW = AF9C9EB2-12AD-4D3E-A4D4-96F6C9966215 {
+    $(WORKSPACE)/$(OUTPUT_DIRECTORY)/$(TARGET)_$(TOOL_CHAIN_TAG)/FV/Vlv.ROM
+  }
+
+FILE RAW = ce57b167-b0e4-41e8-a897-5f4feb781d40 {
+    $(WORKSPACE)/$(OUTPUT_DIRECTORY)/$(TARGET)_$(TOOL_CHAIN_TAG)/FV/CAPSULEDISPATCHFV.Fv
+  }
+
+FILE RAW = 812136D3-4D3A-433A-9418-29BB9BF78F6E {
+    Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosUpdateConfig/SystemBiosUpdateConfig.ini
+  }
+
+[FmpPayload.FmpPayloadBiosPkcs7]
+IMAGE_HEADER_INIT_VERSION = 0x02
+IMAGE_TYPE_ID             = 4096267b-da0a-42eb-b5eb-fef31d207cb4 # System FMP special Guid (do not change it)
+IMAGE_INDEX               = 0x1
+HARDWARE_INSTANCE         = 0x0
+MONOTONIC_COUNT           = 0x2
+CERTIFICATE_GUID          = 4AAFD29D-68DF-49EE-8AA9-347D375665A7 # PKCS7
+
+FILE DATA = $(WORKSPACE)/$(OUTPUT_DIRECTORY)/$(TARGET)_$(TOOL_CHAIN_TAG)/FV/BIOSUPDATECARGO.Fv
+
+[FmpPayload.FmpPayloadBiosRsa2048]
+IMAGE_HEADER_INIT_VERSION = 0x02
+IMAGE_TYPE_ID             = 4096267b-da0a-42eb-b5eb-fef31d207cb4 # System FMP special Guid (do not change it)
+IMAGE_INDEX               = 0x1
+HARDWARE_INSTANCE         = 0x0
+MONOTONIC_COUNT           = 0x2
+CERTIFICATE_GUID          = A7717414-C616-4977-9420-844712A735BF # RSA2048SHA256
+
+FILE DATA = $(WORKSPACE)/$(OUTPUT_DIRECTORY)/$(TARGET)_$(TOOL_CHAIN_TAG)/FV/BIOSUPDATECARGO.Fv
+
+[Capsule.BiosCapsuleFmpPkcs7]
+CAPSULE_GUID                = 6dcbd5ed-e82d-4c44-bda1-7194199ad92a # FMP special Guid (do not change it)
+CAPSULE_FLAGS               = PersistAcrossReset,InitiateReset
+CAPSULE_HEADER_SIZE         = 0x20
+CAPSULE_HEADER_INIT_VERSION = 0x1
+
+FMP_PAYLOAD = FmpPayloadBiosPkcs7
+
+[Capsule.BiosCapsuleFmpRsa2048]
+CAPSULE_GUID                = 6dcbd5ed-e82d-4c44-bda1-7194199ad92a # FMP special Guid (do not change it)
+CAPSULE_FLAGS               = PersistAcrossReset,InitiateReset
+CAPSULE_HEADER_SIZE         = 0x20
+CAPSULE_HEADER_INIT_VERSION = 0x1
+
+FMP_PAYLOAD = FmpPayloadBiosRsa2048
+
diff --git a/Vlv2TbltDevicePkg/PlatformCapsuleGcc.fdf b/Vlv2TbltDevicePkg/PlatformCapsuleGcc.fdf
new file mode 100644
index 0000000..36f78dc
--- /dev/null
+++ b/Vlv2TbltDevicePkg/PlatformCapsuleGcc.fdf
@@ -0,0 +1,81 @@
+## @file
+# FDF file of Platform capsule.
+#
+# Copyright (c) 2016 Intel Corporation.
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution.  The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[FV.BiosUpdateCargo]
+FvAlignment        = 16
+ERASE_POLARITY     = 1
+MEMORY_MAPPED      = TRUE
+STICKY_WRITE       = TRUE
+LOCK_CAP           = TRUE
+LOCK_STATUS        = TRUE
+WRITE_DISABLED_CAP = TRUE
+WRITE_ENABLED_CAP  = TRUE
+WRITE_STATUS       = TRUE
+WRITE_LOCK_CAP     = TRUE
+WRITE_LOCK_STATUS  = TRUE
+READ_DISABLED_CAP  = TRUE
+READ_ENABLED_CAP   = TRUE
+READ_STATUS        = TRUE
+READ_LOCK_CAP      = TRUE
+READ_LOCK_STATUS   = TRUE
+
+FILE RAW = AF9C9EB2-12AD-4D3E-A4D4-96F6C9966215 {
+    $(WORKSPACE)/$(OUTPUT_DIRECTORY)/$(TARGET)_$(TOOL_CHAIN_TAG)/FV/Vlv.ROM
+  }
+
+FILE RAW = ce57b167-b0e4-41e8-a897-5f4feb781d40 {
+    $(WORKSPACE)/$(OUTPUT_DIRECTORY)/$(TARGET)_$(TOOL_CHAIN_TAG)/FV/CAPSULEDISPATCHFV.Fv
+  }
+
+FILE RAW = 812136D3-4D3A-433A-9418-29BB9BF78F6E {
+    Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosUpdateConfig/SystemBiosUpdateConfigGcc.ini
+  }
+
+[FmpPayload.FmpPayloadBiosPkcs7]
+IMAGE_HEADER_INIT_VERSION = 0x02
+IMAGE_TYPE_ID             = 4096267b-da0a-42eb-b5eb-fef31d207cb4 # System FMP special Guid (do not change it)
+IMAGE_INDEX               = 0x1
+HARDWARE_INSTANCE         = 0x0
+MONOTONIC_COUNT           = 0x2
+CERTIFICATE_GUID          = 4AAFD29D-68DF-49EE-8AA9-347D375665A7 # PKCS7
+
+FILE DATA = $(WORKSPACE)/$(OUTPUT_DIRECTORY)/$(TARGET)_$(TOOL_CHAIN_TAG)/FV/BIOSUPDATECARGO.Fv
+
+[FmpPayload.FmpPayloadBiosRsa2048]
+IMAGE_HEADER_INIT_VERSION = 0x02
+IMAGE_TYPE_ID             = 4096267b-da0a-42eb-b5eb-fef31d207cb4 # System FMP special Guid (do not change it)
+IMAGE_INDEX               = 0x1
+HARDWARE_INSTANCE         = 0x0
+MONOTONIC_COUNT           = 0x2
+CERTIFICATE_GUID          = A7717414-C616-4977-9420-844712A735BF # RSA2048SHA256
+
+FILE DATA = $(WORKSPACE)/$(OUTPUT_DIRECTORY)/$(TARGET)_$(TOOL_CHAIN_TAG)/FV/BIOSUPDATECARGO.Fv
+
+[Capsule.BiosCapsuleFmpPkcs7]
+CAPSULE_GUID                = 6dcbd5ed-e82d-4c44-bda1-7194199ad92a # FMP special Guid (do not change it)
+CAPSULE_FLAGS               = PersistAcrossReset,InitiateReset
+CAPSULE_HEADER_SIZE         = 0x20
+CAPSULE_HEADER_INIT_VERSION = 0x1
+
+FMP_PAYLOAD = FmpPayloadBiosPkcs7
+
+[Capsule.BiosCapsuleFmpRsa2048]
+CAPSULE_GUID                = 6dcbd5ed-e82d-4c44-bda1-7194199ad92a # FMP special Guid (do not change it)
+CAPSULE_FLAGS               = PersistAcrossReset,InitiateReset
+CAPSULE_HEADER_SIZE         = 0x20
+CAPSULE_HEADER_INIT_VERSION = 0x1
+
+FMP_PAYLOAD = FmpPayloadBiosRsa2048
+
-- 
2.7.4.windows.1



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

* [PATCH 45/45] Vlv2TbltDevicePkg/bat: add capsule generation in bat.
  2016-09-21  6:44 [PATCH 00/45] Add capsule update and recovery sample Jiewen Yao
                   ` (43 preceding siblings ...)
  2016-09-21  6:45 ` [PATCH 44/45] Vlv2TbltDevicePkg/dsc/fdf: add capsule generation DSC/FDF Jiewen Yao
@ 2016-09-21  6:45 ` Jiewen Yao
  2016-09-21  7:53   ` Wei, David
  2016-09-21 16:35 ` [PATCH 00/45] Add capsule update and recovery sample Kinney, Michael D
                   ` (3 subsequent siblings)
  48 siblings, 1 reply; 83+ messages in thread
From: Jiewen Yao @ 2016-09-21  6:45 UTC (permalink / raw)
  To: edk2-devel
  Cc: David Wei, Feng Tian, Star Zeng, Michael D Kinney, Liming Gao,
	Chao Zhang

If OPENSSL_PATH is set, the build process generates capsule.

Cc: David Wei <david.wei@intel.com>
Cc: Feng Tian <feng.tian@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Chao Zhang <chao.b.zhang@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
---
 Vlv2TbltDevicePkg/bld_vlv.bat | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/Vlv2TbltDevicePkg/bld_vlv.bat b/Vlv2TbltDevicePkg/bld_vlv.bat
index 547b2b1..a01a459 100644
--- a/Vlv2TbltDevicePkg/bld_vlv.bat
+++ b/Vlv2TbltDevicePkg/bld_vlv.bat
@@ -1,7 +1,7 @@
 @REM @file
 @REM   Windows batch file to build BIOS ROM
 @REM
-@REM Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
+@REM Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
 @REM This program and the accompanying materials
 @REM are licensed and made available under the terms and conditions of the BSD License
 @REM which accompanies this distribution.  The full text of the license may be found at
@@ -234,6 +234,7 @@ del /f/q ver_strings >nul
 
 set BIOS_Name=%BOARD_ID%_%Arch%_%BUILD_TYPE%_%VERSION_MAJOR%_%VERSION_MINOR%.ROM
 copy /y/b %BUILD_PATH%\FV\Vlv%Arch%.fd  %WORKSPACE%\%BIOS_Name% >nul
+copy /y/b %BUILD_PATH%\FV\Vlv%Arch%.fd  %BUILD_PATH%\FV\Vlv.ROM >nul
 
 echo.
 echo Build location:     %BUILD_PATH%
@@ -241,6 +242,11 @@ echo BIOS ROM Created:   %BIOS_Name%
 echo.
 echo -------------------- The EDKII BIOS build has successfully completed. --------------------
 echo.
+
+@REM build capsule here
+if "%openssl_path%" == "" goto Exit
+build -p %PLATFORM_PACKAGE%\PlatformCapsule.dsc
+
 goto Exit
 
 :Usage
-- 
2.7.4.windows.1



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

* Re: [PATCH 38/45] Vlv2TbltDevicePkg/PlatformFlashAccessLib: Add instance for capsule update.
  2016-09-21  6:45 ` [PATCH 38/45] Vlv2TbltDevicePkg/PlatformFlashAccessLib: Add instance for capsule update Jiewen Yao
@ 2016-09-21  6:51   ` Wei, David
  0 siblings, 0 replies; 83+ messages in thread
From: Wei, David @ 2016-09-21  6:51 UTC (permalink / raw)
  To: Yao, Jiewen, edk2-devel@lists.01.org
  Cc: Tian, Feng, Zeng, Star, Kinney, Michael D, Gao, Liming,
	Zhang, Chao B

Reviewed-by: David Wei <david.wei@intel.com> 

Thanks,
David  Wei                                 

-----Original Message-----
From: Yao, Jiewen 
Sent: Wednesday, September 21, 2016 2:45 PM
To: edk2-devel@lists.01.org
Cc: Wei, David <david.wei@intel.com>; Tian, Feng <feng.tian@intel.com>; Zeng, Star <star.zeng@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: [PATCH 38/45] Vlv2TbltDevicePkg/PlatformFlashAccessLib: Add instance for capsule update.

Add PlatformFlashAccessLib for capsule update.

Cc: David Wei <david.wei@intel.com>
Cc: Feng Tian <feng.tian@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Chao Zhang <chao.b.zhang@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
---
 Vlv2TbltDevicePkg/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.c   | 192 ++++++++++++++++++++
 Vlv2TbltDevicePkg/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.inf |  47 +++++
 2 files changed, 239 insertions(+)

diff --git a/Vlv2TbltDevicePkg/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.c b/Vlv2TbltDevicePkg/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.c
new file mode 100644
index 0000000..ae8b171
--- /dev/null
+++ b/Vlv2TbltDevicePkg/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.c
@@ -0,0 +1,192 @@
+/** @file
+  Platform Flash Access library.
+
+  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <PiDxe.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PlatformFlashAccessLib.h>
+#include <Library/FlashDeviceLib.h>
+#include <Library/MemoryAllocationLib.h>
+
+#define SECTOR_SIZE_64KB  0x10000      // Common 64kBytes sector size
+#define ALINGED_SIZE  SECTOR_SIZE_64KB
+
+STATIC EFI_PHYSICAL_ADDRESS     mInternalFdAddress;
+
+/**
+  Perform flash write opreation.
+
+  @param FirmwareType      The type of firmware.
+  @param FlashAddress      The address of flash device to be accessed.
+  @param FlashAddressType  The type of flash device address.
+  @param Buffer            The pointer to the data buffer.
+  @param Length            The length of data buffer in bytes.
+
+  @retval EFI_SUCCESS           The operation returns successfully.
+  @retval EFI_WRITE_PROTECTED   The flash device is read only.
+  @retval EFI_UNSUPPORTED       The flash device access is unsupported.
+  @retval EFI_INVALID_PARAMETER The input parameter is not valid.
+**/
+EFI_STATUS
+EFIAPI
+PerformFlashWrite(
+  IN PLATFORM_FIRMWARE_TYPE       FirmwareType,
+  IN EFI_PHYSICAL_ADDRESS         FlashAddress,
+  IN FLASH_ADDRESS_TYPE           FlashAddressType,
+  IN VOID                         *Buffer,
+  IN UINTN                        Length
+  )
+{
+  EFI_STATUS          Status;
+
+  DEBUG((EFI_D_INFO, "PerformFlashWrite - 0x%x(%x) - 0x%x\n", (UINTN)FlashAddress, (UINTN)FlashAddressType, Length));
+  if (FirmwareType >= PlatformFirmwareTypeMax) {
+    return EFI_UNSUPPORTED;
+  }
+  if (FlashAddressType == FlashAddressTypeRelativeAddress) {
+    FlashAddress = FlashAddress + mInternalFdAddress;
+  }
+
+  LibFvbFlashDeviceBlockLock(FlashAddress, Length, FALSE);
+
+  //
+  // Erase & Write
+  //
+  Status = LibFvbFlashDeviceBlockErase((UINTN)FlashAddress, Length);
+  ASSERT_EFI_ERROR(Status);
+  if (EFI_ERROR(Status)) {
+    LibFvbFlashDeviceBlockLock(FlashAddress, Length, TRUE);
+    DEBUG((EFI_D_ERROR, "Flash Erase error\n"));
+    return Status;
+  }
+
+  Status = LibFvbFlashDeviceWrite((UINTN)FlashAddress, &Length, Buffer);
+  ASSERT_EFI_ERROR(Status);
+  if (EFI_ERROR(Status)) {
+    LibFvbFlashDeviceBlockLock(FlashAddress, Length, TRUE);
+    DEBUG((EFI_D_ERROR, "Flash write error\n"));
+    return Status;
+  }
+
+  LibFvbFlashDeviceBlockLock(FlashAddress, Length, TRUE);
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Perform microcode write opreation.
+
+  @param FlashAddress      The address of flash device to be accessed.
+  @param Buffer            The pointer to the data buffer.
+  @param Length            The length of data buffer in bytes.
+
+  @retval EFI_SUCCESS           The operation returns successfully.
+  @retval EFI_WRITE_PROTECTED   The flash device is read only.
+  @retval EFI_UNSUPPORTED       The flash device access is unsupported.
+  @retval EFI_INVALID_PARAMETER The input parameter is not valid.
+**/
+EFI_STATUS
+EFIAPI
+MicrocodeFlashWrite(
+  IN EFI_PHYSICAL_ADDRESS         FlashAddress,
+  IN VOID                         *Buffer,
+  IN UINTN                        Length
+  )
+{
+  EFI_PHYSICAL_ADDRESS         AlignedFlashAddress;
+  VOID                         *AlignedBuffer;
+  UINTN                        AlignedLength;
+  UINTN                        OffsetHead;
+  UINTN                        OffsetTail;
+  EFI_STATUS                   Status;
+
+  DEBUG((EFI_D_INFO, "MicrocodeFlashWrite - 0x%x - 0x%x\n", (UINTN)FlashAddress, Length));
+
+  //
+  // Need make buffer 64K aligned to support ERASE
+  //
+  // [Aligned]    FlashAddress    [Aligned]
+  // |              |                     |
+  // V              V                     V
+  // +--------------+========+------------+
+  // | OffsetHeader | Length | OffsetTail |
+  // +--------------+========+------------+
+  // ^
+  // |<-----------AlignedLength----------->
+  // |
+  // AlignedFlashAddress
+  //
+  OffsetHead = FlashAddress & (ALINGED_SIZE - 1);
+  OffsetTail = (FlashAddress + Length) & (ALINGED_SIZE - 1);
+  if (OffsetTail != 0) {
+    OffsetTail = ALINGED_SIZE - OffsetTail;
+  }
+
+  if ((OffsetHead != 0) || (OffsetTail != 0)) {
+    AlignedFlashAddress = FlashAddress - OffsetHead;
+    AlignedLength = Length + OffsetHead + OffsetTail;
+
+    AlignedBuffer = AllocatePool(AlignedLength);
+    if (AlignedBuffer == NULL) {
+      return EFI_OUT_OF_RESOURCES;
+    }
+    //
+    // Save original buffer
+    //
+    if (OffsetHead != 0) {
+      CopyMem((UINT8 *)AlignedBuffer, (VOID *)AlignedFlashAddress, OffsetHead);
+    }
+    if (OffsetTail != 0) {
+      CopyMem((UINT8 *)AlignedBuffer + OffsetHead + Length, (VOID *)(AlignedFlashAddress + OffsetHead + Length), OffsetTail);
+    }
+    //
+    // Override new buffer
+    //
+    CopyMem((UINT8 *)AlignedBuffer + OffsetHead, Buffer, Length);
+  } else {
+    AlignedFlashAddress = FlashAddress;
+    AlignedBuffer = Buffer;
+    AlignedLength = Length;
+  }
+
+  Status = PerformFlashWrite(
+             PlatformFirmwareTypeBios,
+             AlignedFlashAddress,
+             FlashAddressTypeAbsoluteAddress,
+             AlignedBuffer,
+             AlignedLength
+             );
+  if ((OffsetHead != 0) || (OffsetTail != 0)) {
+    FreePool (AlignedBuffer);
+  }
+  return Status;
+}
+
+/**
+  Platform Flash Access Lib Constructor.
+**/
+EFI_STATUS
+EFIAPI
+PerformFlashAccessLibConstructor (
+  VOID
+  )
+{
+  mInternalFdAddress = FixedPcdGet64(PcdFlashAreaBaseAddress);
+  DEBUG((EFI_D_INFO, "PcdFlashAreaBaseAddress - 0x%x\n", mInternalFdAddress));
+
+  return EFI_SUCCESS;
+}
diff --git a/Vlv2TbltDevicePkg/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.inf b/Vlv2TbltDevicePkg/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.inf
new file mode 100644
index 0000000..18c2809
--- /dev/null
+++ b/Vlv2TbltDevicePkg/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.inf
@@ -0,0 +1,47 @@
+## @file
+#  Platform Flash Access library.
+#
+#  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = PlatformFlashAccessLib
+  FILE_GUID                      = 31CF9CEC-DA4E-4505-AA20-33364A291A95
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = PlatformFlashAccessLib
+  LIBRARY_CLASS                  = MicrocodeFlashAccessLib
+  CONSTRUCTOR                    = PerformFlashAccessLibConstructor
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64 IPF EBC
+#
+
+[Sources]
+  PlatformFlashAccessLib.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  Vlv2TbltDevicePkg/PlatformPkg.dec
+
+[LibraryClasses]
+  BaseMemoryLib
+  PcdLib
+  DebugLib
+  FlashDeviceLib
+  MemoryAllocationLib
+
+[FixedPcd]
+  gPlatformModuleTokenSpaceGuid.PcdFlashAreaBaseAddress
-- 
2.7.4.windows.1



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

* Re: [PATCH 39/45] Vlv2TbltDevicePkg/SystemBiosDescriptor: Add Descriptor for capsule update.
  2016-09-21  6:45 ` [PATCH 39/45] Vlv2TbltDevicePkg/SystemBiosDescriptor: Add Descriptor " Jiewen Yao
@ 2016-09-21  6:54   ` Wei, David
  0 siblings, 0 replies; 83+ messages in thread
From: Wei, David @ 2016-09-21  6:54 UTC (permalink / raw)
  To: Yao, Jiewen, edk2-devel@lists.01.org
  Cc: Tian, Feng, Zeng, Star, Kinney, Michael D, Gao, Liming,
	Zhang, Chao B, Yao, Jiewen

Reviewed-by: David Wei <david.wei@intel.com>

Thanks,
David  Wei                                 


-----Original Message-----
From: Yao, Jiewen 
Sent: Wednesday, September 21, 2016 2:45 PM
To: edk2-devel@lists.01.org
Cc: Wei, David <david.wei@intel.com>; Tian, Feng <feng.tian@intel.com>; Zeng, Star <star.zeng@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: [PATCH 39/45] Vlv2TbltDevicePkg/SystemBiosDescriptor: Add Descriptor for capsule update.

Add SystemBiosDescriptor for capsule update.
The PEIM extracts SystemBiosDescriptor info from FFS and reports it via PCD.

Cc: David Wei <david.wei@intel.com>
Cc: Feng Tian <feng.tian@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Chao Zhang <chao.b.zhang@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
---
 Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptor.aslc | 86 ++++++++++++++++++++
 Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptor.inf  | 45 ++++++++++
 Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptorPei.c | 66 +++++++++++++++
 3 files changed, 197 insertions(+)

diff --git a/Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptor.aslc b/Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptor.aslc
new file mode 100644
index 0000000..a989a7c
--- /dev/null
+++ b/Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptor.aslc
@@ -0,0 +1,86 @@
+/** @file
+  System BIOS descriptor.
+
+  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <PiPei.h>
+#include <Protocol/FirmwareManagement.h>
+#include <Guid/EdkiiSystemFmpCapsule.h>
+
+#define PACKAGE_VERSION                     0xFFFFFFFF
+#define PACKAGE_VERSION_STRING              L"Unknown"
+
+#define CURRENT_FIRMWARE_VERSION            0x00000002
+#define CURRENT_FIRMWARE_VERSION_STRING     L"0x00000002"
+#define LOWEST_SUPPORTED_FIRMWARE_VERSION   0x00000001
+
+#define IMAGE_ID                            SIGNATURE_64('V', 'L', 'V', '2', '_', '_', 'F', 'd')
+#define IMAGE_ID_STRING                     L"Vlv2Fd"
+
+#define IMAGE_TYPE_ID_GUID                  { 0x4096267b, 0xda0a, 0x42eb, { 0xb5, 0xeb, 0xfe, 0xf3, 0x1d, 0x20, 0x7c, 0xb4 } }
+
+typedef struct {
+  EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR  Descriptor;
+  // real string data
+  CHAR16                                  ImageIdNameStr[16];
+  CHAR16                                  VersionNameStr[16];
+  CHAR16                                  PackageVersionNameStr[16];
+} IMAGE_DESCRIPTOR;
+
+IMAGE_DESCRIPTOR mImageDescriptor =
+{
+  {
+    EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR_SIGNATURE,
+    sizeof(EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR),
+    sizeof(IMAGE_DESCRIPTOR),
+    PACKAGE_VERSION,                                       // PackageVersion
+    OFFSET_OF (IMAGE_DESCRIPTOR, PackageVersionNameStr),   // PackageVersionName
+    1,                                                     // ImageIndex;
+    {0x0},                                                 // Reserved
+    IMAGE_TYPE_ID_GUID,                                    // ImageTypeId;
+    IMAGE_ID,                                              // ImageId;
+    OFFSET_OF (IMAGE_DESCRIPTOR, ImageIdNameStr),          // ImageIdName;
+    CURRENT_FIRMWARE_VERSION,                              // Version;
+    OFFSET_OF (IMAGE_DESCRIPTOR, VersionNameStr),          // VersionName;
+    {0x0},                                                 // Reserved2
+    FixedPcdGet32(PcdFlashAreaSize),                       // Size;
+    IMAGE_ATTRIBUTE_IMAGE_UPDATABLE |
+      IMAGE_ATTRIBUTE_RESET_REQUIRED |
+      IMAGE_ATTRIBUTE_IN_USE,                              // AttributesSupported;
+    IMAGE_ATTRIBUTE_IMAGE_UPDATABLE |
+      IMAGE_ATTRIBUTE_RESET_REQUIRED |
+      IMAGE_ATTRIBUTE_IN_USE,                              // AttributesSetting;
+    0x0,                                                   // Compatibilities;
+    LOWEST_SUPPORTED_FIRMWARE_VERSION,                     // LowestSupportedImageVersion;
+    0x00000000,                                            // LastAttemptVersion;
+    0,                                                     // LastAttemptStatus;
+    {0x0},                                                 // Reserved3
+    0,                                                     // HardwareInstance;
+  },
+  // real string data
+  {IMAGE_ID_STRING},
+  {CURRENT_FIRMWARE_VERSION_STRING},
+  {PACKAGE_VERSION_STRING},
+};
+
+
+VOID*
+ReferenceAcpiTable (
+  VOID
+  )
+{
+  //
+  // Reference the table being generated to prevent the optimizer from
+  // removing the data structure from the executable
+  //
+  return (VOID*)&mImageDescriptor;
+}
diff --git a/Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptor.inf b/Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptor.inf
new file mode 100644
index 0000000..812d272
--- /dev/null
+++ b/Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptor.inf
@@ -0,0 +1,45 @@
+## @file
+#  System BIOS descriptor.
+#
+#  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = SystemBiosDescriptor
+  FILE_GUID                      = 90B2B846-CA6D-4D6E-A8D3-C140A8E110AC
+  MODULE_TYPE                    = PEIM
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = SystemBiosDescriptorPeimEntry
+
+[Sources]
+  SystemBiosDescriptorPei.c
+  SystemBiosDescriptor.aslc
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  Vlv2TbltDevicePkg/PlatformPkg.dec
+
+[LibraryClasses]
+  PcdLib
+  PeiServicesLib
+  DebugLib
+  PeimEntryPoint
+
+[FixedPcd]
+  gPlatformModuleTokenSpaceGuid.PcdFlashAreaSize
+
+[Pcd]
+  gEfiMdeModulePkgTokenSpaceGuid.PcdEdkiiSystemFirmwareImageDescriptor
+
+[Depex]
+  TRUE
diff --git a/Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptorPei.c b/Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptorPei.c
new file mode 100644
index 0000000..6272138
--- /dev/null
+++ b/Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptorPei.c
@@ -0,0 +1,66 @@
+/** @file
+  System BIOS descriptor producer.
+
+  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <PiPei.h>
+#include <Library/PcdLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/DebugLib.h>
+#include <Protocol/FirmwareManagement.h>
+#include <Guid/EdkiiSystemFmpCapsule.h>
+
+/**
+  Entrypoint for SystemBiosDescriptor PEIM.
+
+  @param  FileHandle  Handle of the file being invoked.
+  @param  PeiServices Describes the list of possible PEI Services.
+
+  @retval EFI_SUCCESS            PPI successfully installed.
+**/
+EFI_STATUS
+EFIAPI
+SystemBiosDescriptorPeimEntry(
+  IN EFI_PEI_FILE_HANDLE     FileHandle,
+  IN CONST EFI_PEI_SERVICES  **PeiServices
+  )
+{
+  EFI_STATUS                              Status;
+  EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR  *Descriptor;
+  UINTN                                   Size;
+  UINTN                                   Index;
+  UINT32                                  AuthenticationStatus;
+
+  //
+  // Search RAW section.
+  //
+  Index = 0;
+  while (TRUE) {
+    Status = PeiServicesFfsFindSectionData3(EFI_SECTION_RAW, Index, FileHandle, &Descriptor, &AuthenticationStatus);
+    if (EFI_ERROR(Status)) {
+      // Should not happen, must something wrong in FDF.
+      ASSERT(FALSE);
+      return EFI_NOT_FOUND;
+    }
+    if (Descriptor->Signature == EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR_SIGNATURE) {
+      break;
+    }
+    Index++;
+  }
+
+  DEBUG((EFI_D_INFO, "EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR size - 0x%x\n", Descriptor->Length));
+
+  Size = Descriptor->Length;
+  PcdSetPtrS (PcdEdkiiSystemFirmwareImageDescriptor, &Size, Descriptor);
+
+  return EFI_SUCCESS;
+}
-- 
2.7.4.windows.1



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

* Re: [PATCH 40/45] Vlv2TbltDevicePkg/SystemBiosUpdateConfig: Add capsule config file.
  2016-09-21  6:45 ` [PATCH 40/45] Vlv2TbltDevicePkg/SystemBiosUpdateConfig: Add capsule config file Jiewen Yao
@ 2016-09-21  6:57   ` Wei, David
  0 siblings, 0 replies; 83+ messages in thread
From: Wei, David @ 2016-09-21  6:57 UTC (permalink / raw)
  To: Yao, Jiewen, edk2-devel@lists.01.org
  Cc: Tian, Feng, Zeng, Star, Kinney, Michael D, Gao, Liming,
	Zhang, Chao B, Yao, Jiewen

Reviewed-by: David Wei <david.wei@intel.com>

Thanks,
David  Wei                                 


-----Original Message-----
From: Yao, Jiewen 
Sent: Wednesday, September 21, 2016 2:45 PM
To: edk2-devel@lists.01.org
Cc: Wei, David <david.wei@intel.com>; Tian, Feng <feng.tian@intel.com>; Zeng, Star <star.zeng@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: [PATCH 40/45] Vlv2TbltDevicePkg/SystemBiosUpdateConfig: Add capsule config file.

Add SystemBiosUpdateConfig as capsule configuration file.

Cc: David Wei <david.wei@intel.com>
Cc: Feng Tian <feng.tian@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Chao Zhang <chao.b.zhang@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
---
 Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosUpdateConfig/SystemBiosUpdateConfig.ini    | 72 ++++++++++++++++++++
 Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosUpdateConfig/SystemBiosUpdateConfigGcc.ini | 72 ++++++++++++++++++++
 2 files changed, 144 insertions(+)

diff --git a/Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosUpdateConfig/SystemBiosUpdateConfig.ini b/Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosUpdateConfig/SystemBiosUpdateConfig.ini
new file mode 100644
index 0000000..61e254b
--- /dev/null
+++ b/Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosUpdateConfig/SystemBiosUpdateConfig.ini
@@ -0,0 +1,72 @@
+## @file
+#
+#  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Head]
+NumOfUpdate = 6
+NumOfRecovery = 1
+Update0 = Vlv2FvMicrocode
+Update1 = Vlv2FvBinary
+Update2 = Vlv2FvMain
+Update3 = Vlv2FvRecovery2
+Update4 = Vlv2FvRecovery
+Update5 = Vlv2FvNvRam
+Recovery0 = Vlv2FvMain
+
+[Vlv2FvMicrocode]
+FirmwareType = 0            # BIOS
+AddressType = 0             # 0 - relative address, 1 - absolute address.
+BaseAddress = 0x00000000    # Base address offset on flash
+Length      = 0x00040000    # Length
+ImageOffset = 0x00000000    # Image offset of this BIOS update image
+FileGuid    = AF9C9EB2-12AD-4D3E-A4D4-96F6C9966215
+
+[Vlv2FvNvRam]
+UpdateType  = 0             # UpdateWholeFV
+AddressType = 0             # 0 - relative address, 1 - absolute address.
+BaseAddress = 0x00040000    # Base address offset on flash
+Length      = 0x00080000    # Length
+ImageOffset = 0x00040000    # Image offset of this BIOS update image
+FileGuid    = AF9C9EB2-12AD-4D3E-A4D4-96F6C9966215
+
+[Vlv2FvBinary]
+FirmwareType = 0            # BIOS
+AddressType = 0             # 0 - relative address, 1 - absolute address.
+BaseAddress = 0x000C0000    # Base address offset on flash
+Length      = 0x00050000    # Length
+ImageOffset = 0x000C0000    # Image offset of this BIOS update image
+FileGuid    = AF9C9EB2-12AD-4D3E-A4D4-96F6C9966215
+
+[Vlv2FvMain]
+FirmwareType = 1            # NvRam
+AddressType = 0             # 0 - relative address, 1 - absolute address.
+BaseAddress = 0x00110000    # Base address offset on flash
+Length      = 0x00210000    # Length
+ImageOffset = 0x00110000    # Image offset of this BIOS update image
+FileGuid    = AF9C9EB2-12AD-4D3E-A4D4-96F6C9966215
+
+[Vlv2FvRecovery2]
+FirmwareType = 0            # BIOS
+AddressType = 0             # 0 - relative address, 1 - absolute address.
+BaseAddress = 0x00320000    # Base address offset on flash
+Length      = 0x00070000    # Length
+ImageOffset = 0x00320000    # Image offset of this BIOS update image
+FileGuid    = AF9C9EB2-12AD-4D3E-A4D4-96F6C9966215
+
+[Vlv2FvRecovery]
+FirmwareType = 0            # BIOS
+AddressType = 0             # 0 - relative address, 1 - absolute address.
+BaseAddress = 0x00390000    # Base address offset on flash
+Length      = 0x00070000    # Length
+ImageOffset = 0x00390000    # Image offset of this BIOS update image
+FileGuid    = AF9C9EB2-12AD-4D3E-A4D4-96F6C9966215
+
diff --git a/Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosUpdateConfig/SystemBiosUpdateConfigGcc.ini b/Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosUpdateConfig/SystemBiosUpdateConfigGcc.ini
new file mode 100644
index 0000000..40216d4
--- /dev/null
+++ b/Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosUpdateConfig/SystemBiosUpdateConfigGcc.ini
@@ -0,0 +1,72 @@
+## @file
+#
+#  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Head]
+NumOfUpdate = 6
+NumOfRecovery = 1
+Update0 = Vlv2FvMicrocode
+Update1 = Vlv2FvBinary
+Update2 = Vlv2FvMain
+Update3 = Vlv2FvRecovery2
+Update4 = Vlv2FvRecovery
+Update5 = Vlv2FvNvRam
+Recovery0 = Vlv2FvMain
+
+[Vlv2FvMicrocode]
+FirmwareType = 0            # BIOS
+AddressType = 0             # 0 - relative address, 1 - absolute address.
+BaseAddress = 0x00000000    # Base address offset on flash
+Length      = 0x00040000    # Length
+ImageOffset = 0x00000000    # Image offset of this BIOS update image
+FileGuid    = AF9C9EB2-12AD-4D3E-A4D4-96F6C9966215
+
+[Vlv2FvNvRam]
+UpdateType  = 0             # UpdateWholeFV
+AddressType = 0             # 0 - relative address, 1 - absolute address.
+BaseAddress = 0x00040000    # Base address offset on flash
+Length      = 0x00080000    # Length
+ImageOffset = 0x00040000    # Image offset of this BIOS update image
+FileGuid    = AF9C9EB2-12AD-4D3E-A4D4-96F6C9966215
+
+[Vlv2FvBinary]
+FirmwareType = 0            # BIOS
+AddressType = 0             # 0 - relative address, 1 - absolute address.
+BaseAddress = 0x000C0000    # Base address offset on flash
+Length      = 0x00050000    # Length
+ImageOffset = 0x000C0000    # Image offset of this BIOS update image
+FileGuid    = AF9C9EB2-12AD-4D3E-A4D4-96F6C9966215
+
+[Vlv2FvMain]
+FirmwareType = 1            # NvRam
+AddressType = 0             # 0 - relative address, 1 - absolute address.
+BaseAddress = 0x00110000    # Base address offset on flash
+Length      = 0x00215000    # Length
+ImageOffset = 0x00110000    # Image offset of this BIOS update image
+FileGuid    = AF9C9EB2-12AD-4D3E-A4D4-96F6C9966215
+
+[Vlv2FvRecovery2]
+FirmwareType = 0            # BIOS
+AddressType = 0             # 0 - relative address, 1 - absolute address.
+BaseAddress = 0x00325000    # Base address offset on flash
+Length      = 0x0006B000    # Length
+ImageOffset = 0x00325000    # Image offset of this BIOS update image
+FileGuid    = AF9C9EB2-12AD-4D3E-A4D4-96F6C9966215
+
+[Vlv2FvRecovery]
+FirmwareType = 0            # BIOS
+AddressType = 0             # 0 - relative address, 1 - absolute address.
+BaseAddress = 0x00390000    # Base address offset on flash
+Length      = 0x00070000    # Length
+ImageOffset = 0x00390000    # Image offset of this BIOS update image
+FileGuid    = AF9C9EB2-12AD-4D3E-A4D4-96F6C9966215
+
-- 
2.7.4.windows.1



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

* Re: [PATCH 41/45] Vlv2TbltDevicePkg/FlashDeviceLib: Add DXE flash device lib.
  2016-09-21  6:45 ` [PATCH 41/45] Vlv2TbltDevicePkg/FlashDeviceLib: Add DXE flash device lib Jiewen Yao
@ 2016-09-21  7:10   ` Wei, David
  0 siblings, 0 replies; 83+ messages in thread
From: Wei, David @ 2016-09-21  7:10 UTC (permalink / raw)
  To: Yao, Jiewen, edk2-devel@lists.01.org
  Cc: Tian, Feng, Zeng, Star, Kinney, Michael D, Gao, Liming,
	Zhang, Chao B

Reviewed-by: David Wei <david.wei@intel.com>

Thanks,
David  Wei                                 


-----Original Message-----
From: Yao, Jiewen 
Sent: Wednesday, September 21, 2016 2:45 PM
To: edk2-devel@lists.01.org
Cc: Wei, David <david.wei@intel.com>; Tian, Feng <feng.tian@intel.com>; Zeng, Star <star.zeng@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: [PATCH 41/45] Vlv2TbltDevicePkg/FlashDeviceLib: Add DXE flash device lib.

Previous FlashDeviceLib only supports DxeRuntime and Smm.
It cannot be linked with SystemBiosUpdateDxe driver.

So we separate DxeRuntime related code into a standalone file,
and create FlashDeviceLibDxe.inf.

Cc: David Wei <david.wei@intel.com>
Cc: Feng Tian <feng.tian@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Chao Zhang <chao.b.zhang@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
---
 Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLib.c              | 156 +---------------
 Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLib.inf            |   8 +-
 Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLibDxe.c           |  62 +++++++
 Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLibDxe.inf         |  49 +++++
 Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLibDxeRuntimeSmm.c | 188 ++++++++++++++++++++
 Vlv2TbltDevicePkg/Library/FlashDeviceLib/SpiChipDefinitions.h          |   5 +-
 6 files changed, 312 insertions(+), 156 deletions(-)

diff --git a/Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLib.c b/Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLib.c
index afb12c9..d964aa5 100644
--- a/Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLib.c
+++ b/Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLib.c
@@ -1,6 +1,6 @@
 /** @file
 
-  Copyright (c) 2004  - 2014, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2004  - 2016, Intel Corporation. All rights reserved.<BR>
                                                                                    

   This program and the accompanying materials are licensed and made available under

   the terms and conditions of the BSD License that accompanies this distribution.  

@@ -19,14 +19,13 @@
 #include <Library/FlashDeviceLib.h>
 #include <Library/DebugLib.h>
 #include <Library/BaseLib.h>
-#include <Library/UefiBootServicesTableLib.h>
-#include <Library/UefiRuntimeServicesTableLib.h>
 #include <Library/BaseMemoryLib.h>
-#include <Library/UefiRuntimeLib.h>
-#include <Protocol/SmmBase2.h>
 #include <Guid/EventGroup.h>
-#include "SpiChipDefinitions.h"
+#include <Library/SpiFlash.H>
 
+#define FLASH_SIZE  0x400000
+
+#define FLASH_DEVICE_BASE_ADDRESS (0xFFFFFFFF-FLASH_SIZE+1)
 UINTN FlashDeviceBase = FLASH_DEVICE_BASE_ADDRESS;
 
 EFI_SPI_PROTOCOL *mSpiProtocol = NULL;
@@ -320,148 +319,3 @@ LibFvbFlashDeviceBlockLock (
   return Status;
 }
 
-VOID
-EFIAPI
-LibFvbFlashDeviceVirtualAddressChangeNotifyEvent (
-  IN EFI_EVENT        Event,
-  IN VOID             *Context
-  )
-{
-  gRT->ConvertPointer (0, (VOID **) &mSpiProtocol);
-  gRT->ConvertPointer (0, (VOID **) &FlashDeviceBase);
-}
-
-
-/**
-  The library constructuor.
-
-  The function does the necessary initialization work for this library
-  instance. Please put all initialization works in it.
-
-  @param[in]  ImageHandle       The firmware allocated handle for the UEFI image.
-  @param[in]  SystemTable       A pointer to the EFI system table.
-
-  @retval     EFI_SUCCESS       The function always return EFI_SUCCESS for now.
-                                It will ASSERT on error for debug version.
-  @retval     EFI_ERROR         Please reference LocateProtocol for error code details.
-
-**/
-EFI_STATUS
-EFIAPI
-LibFvbFlashDeviceSupportInit (
-  IN EFI_HANDLE         ImageHandle,
-  IN EFI_SYSTEM_TABLE   *SystemTable
-  )
-{
-  EFI_STATUS Status;
-  EFI_EVENT  Event;
-  UINT8                         SfId[3];
-  UINT8                         FlashIndex;
-  UINT8                         SpiReadError;
-  UINT8                         SpiNotMatchError;
-  EFI_SMM_BASE2_PROTOCOL       *SmmBase;
-  BOOLEAN                       InSmm;
-
-  SpiReadError     = 0x00;
-  SpiNotMatchError = 0x00;
-
-  InSmm = FALSE;
-  Status = gBS->LocateProtocol (
-                  &gEfiSmmBase2ProtocolGuid,
-                  NULL,
-                  (void **)&SmmBase
-                  );
-  if (!EFI_ERROR(Status)) {
-    Status = SmmBase->InSmm(SmmBase, &InSmm);
-    if (EFI_ERROR(Status)) {
-      InSmm = FALSE;
-    }
-  }
-
-  if (!InSmm) {
-    Status = gBS->LocateProtocol (
-                  &gEfiSpiProtocolGuid,
-                  NULL,
-                  (VOID **)&mSpiProtocol
-                  );
-    ASSERT_EFI_ERROR (Status);
-
-    Status = gBS->CreateEventEx (
-                  EVT_NOTIFY_SIGNAL,
-                  TPL_NOTIFY,
-                  LibFvbFlashDeviceVirtualAddressChangeNotifyEvent,
-                  NULL,
-                  &gEfiEventVirtualAddressChangeGuid,
-                  &Event
-                  );
-    ASSERT_EFI_ERROR (Status);
-  } else {
-    Status = gBS->LocateProtocol (
-                    &gEfiSmmSpiProtocolGuid,
-                    NULL,
-                    (VOID **)&mSpiProtocol
-                    );
-    ASSERT_EFI_ERROR (Status);
-  }
-
-
-  for (FlashIndex = EnumSpiFlashW25Q64; FlashIndex < EnumSpiFlashMax; FlashIndex++) {
-    Status = mSpiProtocol->Init (mSpiProtocol, &(mInitTable[FlashIndex]));
-    if (!EFI_ERROR (Status)) {
-      //
-      // Read Vendor/Device IDs to check if the driver supports the Serial Flash device.
-      //
-      Status = mSpiProtocol->Execute (
-                               mSpiProtocol,
-                               SPI_READ_ID,
-                               SPI_WREN,
-                               TRUE,
-                               FALSE,
-                               FALSE,
-                               0,
-                               3,
-                               SfId,
-                               EnumSpiRegionAll
-                               );
-      if (!EFI_ERROR (Status)) {
-        if ((SfId[0] == mInitTable[FlashIndex].VendorId)  &&
-            (SfId[1] == mInitTable[FlashIndex].DeviceId0) &&
-            (SfId[2] == mInitTable[FlashIndex].DeviceId1)) {
-            //
-            // Found a matching SPI device, FlashIndex now contains flash device.
-            //
-            DEBUG ((EFI_D_ERROR, "OK - Found SPI Flash Type in SPI Flash Driver, Device Type ID 0 = 0x%02x!\n", mInitTable[FlashIndex].DeviceId0));
-            DEBUG ((EFI_D_ERROR, "Device Type ID 1 = 0x%02x!\n", mInitTable[FlashIndex].DeviceId1));
-
-            if (mInitTable[FlashIndex].BiosStartOffset == (UINTN) (-1)) {
-              DEBUG ((EFI_D_ERROR, "ERROR - The size of BIOS image is bigger than SPI Flash device!\n"));
-              CpuDeadLoop ();
-            }
-            break;
-        } else {
-          SpiNotMatchError++;
-        }
-      } else {
-        SpiReadError++;
-      }
-    }
-  }
-
-  DEBUG ((EFI_D_ERROR, "SPI flash chip VID = 0x%X, DID0 = 0x%X, DID1 = 0x%X\n", SfId[0], SfId[1], SfId[2]));
-
-  if (FlashIndex < EnumSpiFlashMax)  {
-    return EFI_SUCCESS;
-  } else {
-  if (SpiReadError != 0) {
-      DEBUG ((EFI_D_ERROR, "ERROR - SPI Read ID execution failed! Error Count = %d\n", SpiReadError));
-   }    
-    else {
-      if (SpiNotMatchError != 0) {
-        DEBUG ((EFI_D_ERROR, "ERROR - No supported SPI flash chip found! Error Count = %d\n", SpiNotMatchError));
-        DEBUG ((EFI_D_ERROR, "SPI flash chip VID = 0x%X, DID0 = 0x%X, DID1 = 0x%X\n", SfId[0], SfId[1], SfId[2]));
-      }
-    }
-    return EFI_UNSUPPORTED;
-  }
-}
-
diff --git a/Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLib.inf b/Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLib.inf
index 423490e..cddbe60 100644
--- a/Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLib.inf
+++ b/Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLib.inf
@@ -1,6 +1,6 @@
 #
 #
-# Copyright (c)  1999  - 2014, Intel Corporation. All rights reserved
+# Copyright (c)  1999  - 2016, Intel Corporation. All rights reserved
 #                                                                                  

 # This program and the accompanying materials are licensed and made available under

 # the terms and conditions of the BSD License that accompanies this distribution.  

@@ -16,7 +16,7 @@
 
 [Defines]
   INF_VERSION                    = 0x00010005
-  BASE_NAME                      = FlashDeviceLib
+  BASE_NAME                      = FlashDeviceLibRuntimeSmm
   FILE_GUID                      = E38A1C3C-928C-4bf7-B6C1-7F0EF163FAA5
   MODULE_TYPE                    = DXE_DRIVER
   VERSION_STRING                 = 1.0
@@ -32,6 +32,7 @@
 
 [Sources]
   FlashDeviceLib.c
+  FlashDeviceLibDxeRuntimeSmm.c
 
 
 [Packages]
@@ -43,6 +44,9 @@
 [LibraryClasses]
   DebugLib
 
+[Guids]
+  gEfiEventVirtualAddressChangeGuid
+
 [Protocols]
   gEfiSpiProtocolGuid
   gEfiSmmSpiProtocolGuid
diff --git a/Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLibDxe.c b/Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLibDxe.c
new file mode 100644
index 0000000..bff9823
--- /dev/null
+++ b/Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLibDxe.c
@@ -0,0 +1,62 @@
+/** @file
+
+  Copyright (c) 2004  - 2016, Intel Corporation. All rights reserved.<BR>
+                                                                                   

+  This program and the accompanying materials are licensed and made available under

+  the terms and conditions of the BSD License that accompanies this distribution.  

+  The full text of the license may be found at                                     

+  http://opensource.org/licenses/bsd-license.php.                                  

+                                                                                   

+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,            

+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.    

+                                                                                   

+
+
+**/
+
+#include <PiDxe.h>
+
+#include <Library/FlashDeviceLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/BaseMemoryLib.h>
+#include "SpiChipDefinitions.h"
+
+extern UINTN FlashDeviceBase;
+
+extern EFI_SPI_PROTOCOL *mSpiProtocol;
+
+/**
+  The library constructuor.
+
+  The function does the necessary initialization work for this library
+  instance. Please put all initialization works in it.
+
+  @param[in]  ImageHandle       The firmware allocated handle for the UEFI image.
+  @param[in]  SystemTable       A pointer to the EFI system table.
+
+  @retval     EFI_SUCCESS       The function always return EFI_SUCCESS for now.
+                                It will ASSERT on error for debug version.
+  @retval     EFI_ERROR         Please reference LocateProtocol for error code details.
+
+**/
+EFI_STATUS
+EFIAPI
+LibFvbFlashDeviceSupportInit (
+  IN EFI_HANDLE         ImageHandle,
+  IN EFI_SYSTEM_TABLE   *SystemTable
+  )
+{
+  EFI_STATUS Status;
+  Status = gBS->LocateProtocol (
+                  &gEfiSpiProtocolGuid,
+                  NULL,
+                  (VOID **)&mSpiProtocol
+                  );
+  ASSERT_EFI_ERROR (Status);
+  // There is no need to call Init, because Runtime or SMM FVB already does that.
+  DEBUG((EFI_D_ERROR, "LibFvbFlashDeviceSupportInit - no init\n"));
+  return EFI_SUCCESS;
+}
+
diff --git a/Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLibDxe.inf b/Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLibDxe.inf
new file mode 100644
index 0000000..cb2ada6
--- /dev/null
+++ b/Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLibDxe.inf
@@ -0,0 +1,49 @@
+#
+#
+# Copyright (c)  1999  - 2016, Intel Corporation. All rights reserved
+#                                                                                  

+# This program and the accompanying materials are licensed and made available under

+# the terms and conditions of the BSD License that accompanies this distribution.  

+# The full text of the license may be found at                                     

+# http://opensource.org/licenses/bsd-license.php.                                  

+#                                                                                  

+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,            

+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.    

+#                                                                                  

+#
+#
+
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = FlashDeviceLibDxe
+  FILE_GUID                      = F0D7222F-FD43-4A5D-B8BF-A259C87AE3B2
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = FlashDeviceLib | DXE_DRIVER
+  CONSTRUCTOR 				     = LibFvbFlashDeviceSupportInit
+
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64
+#
+
+[Sources]
+  FlashDeviceLib.c
+  FlashDeviceLibDxe.c
+
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  Vlv2TbltDevicePkg/PlatformPkg.dec
+  Vlv2DeviceRefCodePkg/Vlv2DeviceRefCodePkg.dec
+
+[LibraryClasses]
+  DebugLib
+
+[Protocols]
+  gEfiSpiProtocolGuid
+
diff --git a/Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLibDxeRuntimeSmm.c b/Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLibDxeRuntimeSmm.c
new file mode 100644
index 0000000..4e9fc46
--- /dev/null
+++ b/Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLibDxeRuntimeSmm.c
@@ -0,0 +1,188 @@
+/** @file
+
+  Copyright (c) 2004  - 2016, Intel Corporation. All rights reserved.<BR>
+                                                                                   
+
+  This program and the accompanying materials are licensed and made available under
+
+  the terms and conditions of the BSD License that accompanies this distribution.  
+
+  The full text of the license may be found at                                     
+
+  http://opensource.org/licenses/bsd-license.php.                                  
+
+                                                                                   
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,            
+
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.    
+
+                                                                                   
+
+
+
+**/
+
+#include <PiDxe.h>
+
+#include <Library/FlashDeviceLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiRuntimeLib.h>
+#include <Protocol/SmmBase2.h>
+#include <Guid/EventGroup.h>
+#include "SpiChipDefinitions.h"
+
+extern UINTN FlashDeviceBase;
+
+extern EFI_SPI_PROTOCOL *mSpiProtocol;
+
+VOID
+EFIAPI
+LibFvbFlashDeviceVirtualAddressChangeNotifyEvent (
+  IN EFI_EVENT        Event,
+  IN VOID             *Context
+  )
+{
+  gRT->ConvertPointer (0, (VOID **) &mSpiProtocol);
+  gRT->ConvertPointer (0, (VOID **) &FlashDeviceBase);
+}
+
+
+/**
+  The library constructuor.
+
+  The function does the necessary initialization work for this library
+  instance. Please put all initialization works in it.
+
+  @param[in]  ImageHandle       The firmware allocated handle for the UEFI image.
+  @param[in]  SystemTable       A pointer to the EFI system table.
+
+  @retval     EFI_SUCCESS       The function always return EFI_SUCCESS for now.
+                                It will ASSERT on error for debug version.
+  @retval     EFI_ERROR         Please reference LocateProtocol for error code details.
+
+**/
+EFI_STATUS
+EFIAPI
+LibFvbFlashDeviceSupportInit (
+  IN EFI_HANDLE         ImageHandle,
+  IN EFI_SYSTEM_TABLE   *SystemTable
+  )
+{
+  EFI_STATUS Status;
+  EFI_EVENT  Event;
+  UINT8                         SfId[3];
+  UINT8                         FlashIndex;
+  UINT8                         SpiReadError;
+  UINT8                         SpiNotMatchError;
+  EFI_SMM_BASE2_PROTOCOL       *SmmBase;
+  BOOLEAN                       InSmm;
+
+  SpiReadError     = 0x00;
+  SpiNotMatchError = 0x00;
+
+  InSmm = FALSE;
+  Status = gBS->LocateProtocol (
+                  &gEfiSmmBase2ProtocolGuid,
+                  NULL,
+                  (void **)&SmmBase
+                  );
+  if (!EFI_ERROR(Status)) {
+    Status = SmmBase->InSmm(SmmBase, &InSmm);
+    if (EFI_ERROR(Status)) {
+      InSmm = FALSE;
+    }
+  }
+
+  if (!InSmm) {
+    Status = gBS->LocateProtocol (
+                  &gEfiSpiProtocolGuid,
+                  NULL,
+                  (VOID **)&mSpiProtocol
+                  );
+    ASSERT_EFI_ERROR (Status);
+
+    Status = gBS->CreateEventEx (
+                  EVT_NOTIFY_SIGNAL,
+                  TPL_NOTIFY,
+                  LibFvbFlashDeviceVirtualAddressChangeNotifyEvent,
+                  NULL,
+                  &gEfiEventVirtualAddressChangeGuid,
+                  &Event
+                  );
+    ASSERT_EFI_ERROR (Status);
+
+  } else {
+    Status = gBS->LocateProtocol (
+                    &gEfiSmmSpiProtocolGuid,
+                    NULL,
+                    (VOID **)&mSpiProtocol
+                    );
+    ASSERT_EFI_ERROR (Status);
+  }
+
+
+  for (FlashIndex = EnumSpiFlashW25Q64; FlashIndex < EnumSpiFlashMax; FlashIndex++) {
+    Status = mSpiProtocol->Init (mSpiProtocol, &(mInitTable[FlashIndex]));
+    if (!EFI_ERROR (Status)) {
+      //
+      // Read Vendor/Device IDs to check if the driver supports the Serial Flash device.
+      //
+      Status = mSpiProtocol->Execute (
+                               mSpiProtocol,
+                               SPI_READ_ID,
+                               SPI_WREN,
+                               TRUE,
+                               FALSE,
+                               FALSE,
+                               0,
+                               3,
+                               SfId,
+                               EnumSpiRegionAll
+                               );
+      if (!EFI_ERROR (Status)) {
+        if ((SfId[0] == mInitTable[FlashIndex].VendorId)  &&
+            (SfId[1] == mInitTable[FlashIndex].DeviceId0) &&
+            (SfId[2] == mInitTable[FlashIndex].DeviceId1)) {
+            //
+            // Found a matching SPI device, FlashIndex now contains flash device.
+            //
+            DEBUG ((EFI_D_ERROR, "OK - Found SPI Flash Type in SPI Flash Driver, Device Type ID 0 = 0x%02x!\n", mInitTable[FlashIndex].DeviceId0));
+            DEBUG ((EFI_D_ERROR, "Device Type ID 1 = 0x%02x!\n", mInitTable[FlashIndex].DeviceId1));
+
+            if (mInitTable[FlashIndex].BiosStartOffset == (UINTN) (-1)) {
+              DEBUG ((EFI_D_ERROR, "ERROR - The size of BIOS image is bigger than SPI Flash device!\n"));
+              CpuDeadLoop ();
+            }
+            break;
+        } else {
+          SpiNotMatchError++;
+        }
+      } else {
+        SpiReadError++;
+      }
+    }
+  }
+
+  DEBUG ((EFI_D_ERROR, "SPI flash chip VID = 0x%X, DID0 = 0x%X, DID1 = 0x%X\n", SfId[0], SfId[1], SfId[2]));
+
+  if (FlashIndex < EnumSpiFlashMax)  {
+    return EFI_SUCCESS;
+  } else {
+  if (SpiReadError != 0) {
+      DEBUG ((EFI_D_ERROR, "ERROR - SPI Read ID execution failed! Error Count = %d\n", SpiReadError));
+   }
+    else {
+      if (SpiNotMatchError != 0) {
+        DEBUG ((EFI_D_ERROR, "ERROR - No supported SPI flash chip found! Error Count = %d\n", SpiNotMatchError));
+        DEBUG ((EFI_D_ERROR, "SPI flash chip VID = 0x%X, DID0 = 0x%X, DID1 = 0x%X\n", SfId[0], SfId[1], SfId[2]));
+      }
+    }
+    return EFI_UNSUPPORTED;
+  }
+}
+
diff --git a/Vlv2TbltDevicePkg/Library/FlashDeviceLib/SpiChipDefinitions.h b/Vlv2TbltDevicePkg/Library/FlashDeviceLib/SpiChipDefinitions.h
index 15bd1e0..fbde4e6 100644
--- a/Vlv2TbltDevicePkg/Library/FlashDeviceLib/SpiChipDefinitions.h
+++ b/Vlv2TbltDevicePkg/Library/FlashDeviceLib/SpiChipDefinitions.h
@@ -1,6 +1,6 @@
 /*++
 
-  Copyright (c) 2004  - 2014, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2004  - 2016, Intel Corporation. All rights reserved.<BR>
                                                                                    

   This program and the accompanying materials are licensed and made available under

   the terms and conditions of the BSD License that accompanies this distribution.  

@@ -16,8 +16,7 @@
 
 #include <Library/SpiFlash.H>
 
-#define FLASH_SIZE  0x300000
-#define FLASH_DEVICE_BASE_ADDRESS (0xFFFFFFFF-FLASH_SIZE+1)
+#define FLASH_SIZE  0x400000
 
 //
 // Serial Flash device initialization data table provided to the
-- 
2.7.4.windows.1



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

* Re: [PATCH 45/45] Vlv2TbltDevicePkg/bat: add capsule generation in bat.
  2016-09-21  6:45 ` [PATCH 45/45] Vlv2TbltDevicePkg/bat: add capsule generation in bat Jiewen Yao
@ 2016-09-21  7:53   ` Wei, David
  2016-09-21  7:54     ` Yao, Jiewen
  0 siblings, 1 reply; 83+ messages in thread
From: Wei, David @ 2016-09-21  7:53 UTC (permalink / raw)
  To: Yao, Jiewen, edk2-devel@lists.01.org
  Cc: Tian, Feng, Zeng, Star, Kinney, Michael D, Gao, Liming,
	Zhang, Chao B, Wei, David

Hi Jiewen,

Only one comment: it's better if we add a help message for this build option.  

Reviewed-by: David Wei <david.wei@intel.com>

Thanks,
David  Wei                                 


-----Original Message-----
From: Yao, Jiewen 
Sent: Wednesday, September 21, 2016 2:45 PM
To: edk2-devel@lists.01.org
Cc: Wei, David <david.wei@intel.com>; Tian, Feng <feng.tian@intel.com>; Zeng, Star <star.zeng@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: [PATCH 45/45] Vlv2TbltDevicePkg/bat: add capsule generation in bat.

If OPENSSL_PATH is set, the build process generates capsule.

Cc: David Wei <david.wei@intel.com>
Cc: Feng Tian <feng.tian@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Chao Zhang <chao.b.zhang@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
---
 Vlv2TbltDevicePkg/bld_vlv.bat | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/Vlv2TbltDevicePkg/bld_vlv.bat b/Vlv2TbltDevicePkg/bld_vlv.bat
index 547b2b1..a01a459 100644
--- a/Vlv2TbltDevicePkg/bld_vlv.bat
+++ b/Vlv2TbltDevicePkg/bld_vlv.bat
@@ -1,7 +1,7 @@
 @REM @file
 @REM   Windows batch file to build BIOS ROM
 @REM
-@REM Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
+@REM Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
 @REM This program and the accompanying materials
 @REM are licensed and made available under the terms and conditions of the BSD License
 @REM which accompanies this distribution.  The full text of the license may be found at
@@ -234,6 +234,7 @@ del /f/q ver_strings >nul
 
 set BIOS_Name=%BOARD_ID%_%Arch%_%BUILD_TYPE%_%VERSION_MAJOR%_%VERSION_MINOR%.ROM
 copy /y/b %BUILD_PATH%\FV\Vlv%Arch%.fd  %WORKSPACE%\%BIOS_Name% >nul
+copy /y/b %BUILD_PATH%\FV\Vlv%Arch%.fd  %BUILD_PATH%\FV\Vlv.ROM >nul
 
 echo.
 echo Build location:     %BUILD_PATH%
@@ -241,6 +242,11 @@ echo BIOS ROM Created:   %BIOS_Name%
 echo.
 echo -------------------- The EDKII BIOS build has successfully completed. --------------------
 echo.
+
+@REM build capsule here
+if "%openssl_path%" == "" goto Exit
+build -p %PLATFORM_PACKAGE%\PlatformCapsule.dsc
+
 goto Exit
 
 :Usage
-- 
2.7.4.windows.1



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

* Re: [PATCH 45/45] Vlv2TbltDevicePkg/bat: add capsule generation in bat.
  2016-09-21  7:53   ` Wei, David
@ 2016-09-21  7:54     ` Yao, Jiewen
  0 siblings, 0 replies; 83+ messages in thread
From: Yao, Jiewen @ 2016-09-21  7:54 UTC (permalink / raw)
  To: Wei, David, edk2-devel@lists.01.org
  Cc: Tian, Feng, Zeng, Star, Kinney, Michael D, Gao, Liming,
	Zhang, Chao B, Yao, Jiewen

That is very good suggestion.
I will generate one more patch to add help info.



> -----Original Message-----
> From: Wei, David
> Sent: Wednesday, September 21, 2016 3:54 PM
> To: Yao, Jiewen <jiewen.yao@intel.com>; edk2-devel@lists.01.org
> Cc: Tian, Feng <feng.tian@intel.com>; Zeng, Star <star.zeng@intel.com>;
> Kinney, Michael D <michael.d.kinney@intel.com>; Gao, Liming
> <liming.gao@intel.com>; Zhang, Chao B <chao.b.zhang@intel.com>; Wei,
> David <david.wei@intel.com>
> Subject: RE: [PATCH 45/45] Vlv2TbltDevicePkg/bat: add capsule generation
> in bat.
> 
> Hi Jiewen,
> 
> Only one comment: it's better if we add a help message for this build option.
> 
> Reviewed-by: David Wei <david.wei@intel.com>
> 
> Thanks,
> David  Wei
> 
> 
> -----Original Message-----
> From: Yao, Jiewen
> Sent: Wednesday, September 21, 2016 2:45 PM
> To: edk2-devel@lists.01.org
> Cc: Wei, David <david.wei@intel.com>; Tian, Feng <feng.tian@intel.com>;
> Zeng, Star <star.zeng@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: [PATCH 45/45] Vlv2TbltDevicePkg/bat: add capsule generation in
> bat.
> 
> If OPENSSL_PATH is set, the build process generates capsule.
> 
> Cc: David Wei <david.wei@intel.com>
> Cc: Feng Tian <feng.tian@intel.com>
> Cc: Star Zeng <star.zeng@intel.com>
> Cc: Michael D Kinney <michael.d.kinney@intel.com>
> Cc: Liming Gao <liming.gao@intel.com>
> Cc: Chao Zhang <chao.b.zhang@intel.com>
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
> ---
>  Vlv2TbltDevicePkg/bld_vlv.bat | 8 +++++++-
>  1 file changed, 7 insertions(+), 1 deletion(-)
> 
> diff --git a/Vlv2TbltDevicePkg/bld_vlv.bat b/Vlv2TbltDevicePkg/bld_vlv.bat
> index 547b2b1..a01a459 100644
> --- a/Vlv2TbltDevicePkg/bld_vlv.bat
> +++ b/Vlv2TbltDevicePkg/bld_vlv.bat
> @@ -1,7 +1,7 @@
>  @REM @file
>  @REM   Windows batch file to build BIOS ROM
>  @REM
> -@REM Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
> +@REM Copyright (c) 2006 - 2016, Intel Corporation. All rights
> reserved.<BR>
>  @REM This program and the accompanying materials
>  @REM are licensed and made available under the terms and conditions of
> the BSD License
>  @REM which accompanies this distribution.  The full text of the license
> may be found at
> @@ -234,6 +234,7 @@ del /f/q ver_strings >nul
> 
>  set
> BIOS_Name=%BOARD_ID%_%Arch%_%BUILD_TYPE%_%VERSION_MAJOR%
> _%VERSION_MINOR%.ROM
>  copy
> /y/b %BUILD_PATH%\FV\Vlv%Arch%.fd  %WORKSPACE%\%BIOS_Name% >
> nul
> +copy
> /y/b %BUILD_PATH%\FV\Vlv%Arch%.fd  %BUILD_PATH%\FV\Vlv.ROM >nul
> 
>  echo.
>  echo Build location:     %BUILD_PATH%
> @@ -241,6 +242,11 @@ echo BIOS ROM Created:   %BIOS_Name%
>  echo.
>  echo -------------------- The EDKII BIOS build has successfully completed.
> --------------------
>  echo.
> +
> +@REM build capsule here
> +if "%openssl_path%" == "" goto Exit
> +build -p %PLATFORM_PACKAGE%\PlatformCapsule.dsc
> +
>  goto Exit
> 
>  :Usage
> --
> 2.7.4.windows.1



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

* Re: [PATCH 00/45] Add capsule update and recovery sample.
  2016-09-21  6:44 [PATCH 00/45] Add capsule update and recovery sample Jiewen Yao
                   ` (44 preceding siblings ...)
  2016-09-21  6:45 ` [PATCH 45/45] Vlv2TbltDevicePkg/bat: add capsule generation in bat Jiewen Yao
@ 2016-09-21 16:35 ` Kinney, Michael D
  2016-09-22  1:59   ` Yao, Jiewen
  2016-09-23  3:18 ` Gao, Liming
                   ` (2 subsequent siblings)
  48 siblings, 1 reply; 83+ messages in thread
From: Kinney, Michael D @ 2016-09-21 16:35 UTC (permalink / raw)
  To: Yao, Jiewen, edk2-devel@lists.01.org, Kinney, Michael D
  Cc: Tian, Feng, Gao, Liming, Zeng, Star, Fan, Jeff, Zhang, Chao B

Jiewen,

Thanks for this contribution and thank you for also providing a version of
it on your GitHub fork to make it easier for some to evaluate such a large
series.

Can you provide a more detailed summary of this feature along with 
A summary of any testing that has already been performed?

I see some of the comments have a Caution about an API taking external
input.  This implies that some amount of security analysis and review
may have already been performed.  The summary should include the set of 
APIs that do take external input and what review or testing was done on 
those APIs?

What amount of additional testing do you think this series requires?

Thanks,

Mike

> -----Original Message-----
> From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of Jiewen Yao
> Sent: Tuesday, September 20, 2016 11:45 PM
> To: edk2-devel@lists.01.org
> Cc: Tian, Feng <feng.tian@intel.com>; Gao, Liming <liming.gao@intel.com>; Zeng, Star
> <star.zeng@intel.com>; Kinney, Michael D <michael.d.kinney@intel.com>; Fan, Jeff
> <jeff.fan@intel.com>; Zhang, Chao B <chao.b.zhang@intel.com>
> Subject: [edk2] [PATCH 00/45] Add capsule update and recovery sample.
> 
> This series patch provides sample on how to do signed capsule update
> and recovery in EDKII.
> 
> This series patch is also checked into git@github.com:jyao1/edk2.git.
> 
> The feature includes:
> 1) Define EDKII signed system BIOS capsule format.
> 2) Provide EDKII signed system BIOS update sample.
> 3) Provide EDKII signed recovery sample.
> 4) Provide Microcode update sample for X86 system.
> 5) Update Quark to use new capsule/recovery solution.
> 6) Update Vlv2(MinnowMax) to use new capsule/recovery solution.
> 
> The signed capsule/recovery solution is in MdeModulePkg.
> The capsule in IntelFrameworkModulePkg is deprecated.
> The Microcode update solution is in UefiCpuPkg.
> 
> Cc: Feng Tian <feng.tian@intel.com>
> Cc: Star Zeng <star.zeng@intel.com>
> Cc: Michael D Kinney <michael.d.kinney@intel.com>
> Cc: Liming Gao <liming.gao@intel.com>
> Cc: Chao Zhang <chao.b.zhang@intel.com>
> Cc: Jeff Fan <jeff.fan@intel.com>
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
> 
> 
> Jiewen Yao (45):
>   MdeModulePkg/Include: Add EDKII system FMP capsule header.
>   MdeModulePkg/Include: Add EdkiiSystemCapsuleLib definition.
>   MdeModulePkg/Include: Add FmpAuthenticationLib header.
>   MdeModulePkg/Include: Add IniParsingLib header.
>   MdeModulePkg/Include: Add PlatformFlashAccessLib header.
>   MdeModulePkg/CapsuleLib: Add ProcessCapsules() API.
>   MdeModulePkg/MdeModulePkg.dec: Add capsule related definition.
>   MdeModulePkg/IniParsingLib: Add InitParsingLib instance.
>   MdeModulePkg/FmpAuthenticationLib: Add FmpAuthenticationLib instance.
>   MdeModulePkg/DxeCapsuleLibFmp: Add DxeCapsuleLibFmp instance.
>   MdeModulePkg/DxeCapsuleLibNull: Add ProcessCapsules() interface.
>   MdeModulePkg/EdkiiSystemCapsuleLib: Add EdkiiSystemCapsuleLib
>     instance.
>   MdeModulePkg/PlatformFlashAccessLib: Add NULL PlatformFlashAccessLib.
>   MdeModulePkg/Esrt: Add ESRT_FW_TYPE_SYSTEMFIRMWARE check.
>   MdeModulePkg/SystemBiosUpdate: Add SystemBiosUpdate component.
>   MdeModulePkg/RecoveryModuleLoadPei: Add RecoveryModuleLoadPei.
>   MdeModulePkg/CapsuleApp: Add CapsuleApp application.
>   MdeModulePkg/MdeModulePkg.dsc: Add capsule related component.
>   IntelFrameworkModulePkg/DxeCapsuleLib: Add ProcessCapsules()
>     interface.
>   SecurityPkg/SecurityPkg.dec: Add PcdPkcs7CertBuffer PCD.
>   SecurityPkg/FmpAuthenticationPkcs7Lib: Add PKCS7 NULL class for FMP.
>   SecurityPkg/FmpAuthenticationRsa2048Sha256Lib: Add NULL class for FMP.
>   SecurityPkg/SecurityPkg.dsc: Add FmpAuthentication*Lib.
>   UefiCpuPkg/Include: Add Microcode FMP definition.
>   UefiCpuPkg/Include: Add MicrocodeFlashAccessLib header.
>   UefiCpuPkg/UefiCpuPkg.dec: Add Microcode capsule related definition.
>   UefiCpuPkg/MicrocodeUpdate: Add MicrocodeUpdate component.
>   UefiCpuPkg/MicrocodeFlashAccessLib: Add NULL MicrocodeFlashAccessLib.
>   UefiCpuPkg/MicrocodeCapsuleApp: Add MicrocodeCapsuleApp application.
>   UefiCpuPkg/UefiCpuPkg.dsc: Add MicrocodeCapsule related component.
>   QuarkPlatformPkg/PlatformFlashAccessLib: Add instance for capsule
>     update.
>   QuarkPlatformPkg/SystemBiosDescriptor: Add Descriptor for capsule
>     update.
>   QuarkPlatformPkg/SystemBiosUpdateConfig: Add capsule config file.
>   QuarkPlatformPkg/PlatformInit: Remove recovery PPI installation.
>   QuarkPlatformPkg/PlatformBootManager: Add capsule/recovery handling.
>   QuarkPlatformPkg/dsc/fdf: Add capsule/recovery support.
>   QuarkPlatformPkg/dsc/fdf: add capsule generation DSC/FDF.
>   Vlv2TbltDevicePkg/PlatformFlashAccessLib: Add instance for capsule
>     update.
>   Vlv2TbltDevicePkg/SystemBiosDescriptor: Add Descriptor for capsule
>     update.
>   Vlv2TbltDevicePkg/SystemBiosUpdateConfig: Add capsule config file.
>   Vlv2TbltDevicePkg/FlashDeviceLib: Add DXE flash device lib.
>   Vlv2TbltDevicePkg/PlatformBootManager: Add capsule/recovery handling.
>   Vlv2TbltDevicePkg/dsc/fdf: Add capsule/recovery support.
>   Vlv2TbltDevicePkg/dsc/fdf: add capsule generation DSC/FDF.
>   Vlv2TbltDevicePkg/bat: add capsule generation in bat.
> 
>  IntelFrameworkModulePkg/Library/DxeCapsuleLib/DxeCapsuleLib.c
> |   39 +-
>  MdeModulePkg/Application/CapsuleApp/AppSupport.c
> |  480 ++++++
>  MdeModulePkg/Application/CapsuleApp/CapsuleApp.c
> | 1047 +++++++++++++
>  MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf
> |   71 +
>  MdeModulePkg/Application/CapsuleApp/CapsuleApp.uni
> |   22 +
>  MdeModulePkg/Application/CapsuleApp/CapsuleAppExtra.uni
> |   19 +
>  MdeModulePkg/Application/CapsuleApp/CapsuleDump.c
> |  840 +++++++++++
>  MdeModulePkg/Include/Guid/EdkiiSystemFmpCapsule.h
> |  110 ++
>  MdeModulePkg/Include/Library/CapsuleLib.h
> |   45 +-
>  MdeModulePkg/Include/Library/EdkiiSystemCapsuleLib.h
> |  152 ++
>  MdeModulePkg/Include/Library/FmpAuthenticationLib.h
> |   91 ++
>  MdeModulePkg/Include/Library/IniParsingLib.h
> |  153 ++
>  MdeModulePkg/Include/Library/PlatformFlashAccessLib.h
> |   59 +
>  MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.c
> | 1538 ++++++++++++++++++++
>  MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.inf
> |   82 ++
>  MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.uni
> |   22 +
>  MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleProcessLib.c
> |  517 +++++++
>  MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleReportLib.c
> |  447 ++++++
>  MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleRuntime.c
> |  112 ++
>  MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf
> |   85 ++
>  MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.uni
> |   22 +
>  MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.c
> |   47 +-
>  MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.c
> |  609 ++++++++
>  MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.inf
> |   55 +
>  MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.uni
> |   22 +
>  MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.c
> |  274 ++++
>  MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.inf
> |   47 +
>  MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.uni
> |   22 +
>  MdeModulePkg/Library/IniParsingLib/IniParsingLib.c
> | 1053 ++++++++++++++
>  MdeModulePkg/Library/IniParsingLib/IniParsingLib.inf
> |   42 +
>  MdeModulePkg/Library/IniParsingLib/IniParsingLib.uni
> |   22 +
>  MdeModulePkg/Library/PlatformFlashAccessLibNull/PlatformFlashAccessLibNull.c
> |   54 +
>  MdeModulePkg/Library/PlatformFlashAccessLibNull/PlatformFlashAccessLibNull.inf
> |   40 +
>  MdeModulePkg/Library/PlatformFlashAccessLibNull/PlatformFlashAccessLibNull.uni
> |   21 +
>  MdeModulePkg/MdeModulePkg.dec
> |  106 ++
>  MdeModulePkg/MdeModulePkg.dsc
> |   24 +
>  MdeModulePkg/Universal/EsrtDxe/EsrtDxe.inf
> |    3 +-
>  MdeModulePkg/Universal/EsrtDxe/EsrtImpl.c
> |   37 +-
>  MdeModulePkg/Universal/RecoveryModuleLoadPei/ParseConfigProfile.c
> |  158 ++
>  MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPei.c
> |  746 ++++++++++
>  MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPei.h
> |   44 +
>  MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPei.inf
> |   71 +
>  MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPei.uni
> |   21 +
>  MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPeiExtra.uni
> |   20 +
>  MdeModulePkg/Universal/SystemBiosUpdate/ParseConfigProfile.c
> |  219 +++
>  MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosDxe.h
> |  393 +++++
>  MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosMainDxe.c
> |  484 ++++++
>  MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosMainSetImage.c
> |  453 ++++++
>  MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosMainSetImageDummy.c
> |   90 ++
>  MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxe.inf
> |   66 +
>  MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxe.uni
> |   21 +
>  MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxeExtra.uni
> |   20 +
>  MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxe.inf
> |   70 +
>  MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxe.uni
> |   21 +
>  MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxeExtra.uni
> |   20 +
> 
> QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLi
> bDxe.c   |  200 +++
> 
> QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLi
> bDxe.inf |   52 +
>  QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/SpiFlashDevice.c
> |  336 +++++
>  QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/SpiFlashDevice.h
> |  186 +++
>  QuarkPlatformPkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptor.aslc
> |   88 ++
>  QuarkPlatformPkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptor.inf
> |   45 +
>  QuarkPlatformPkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptorPei.c
> |   66 +
>  QuarkPlatformPkg/Feature/Capsule/SystemBiosUpdateConfig/SystemBiosUpdateConfig.ini
> |   62 +
>  QuarkPlatformPkg/Library/PlatformBootManagerLib/PlatformBootManager.c
> |   95 +-
>  QuarkPlatformPkg/Library/PlatformBootManagerLib/PlatformBootManager.h
> |    8 +-
>  QuarkPlatformPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf
> |    8 +-
>  QuarkPlatformPkg/Platform/Pei/PlatformInit/MemoryCallback.c
> |    3 +-
>  QuarkPlatformPkg/Quark.dsc
> |   61 +-
>  QuarkPlatformPkg/Quark.fdf
> |   53 +
>  QuarkPlatformPkg/QuarkCapsule.dsc
> |   44 +
>  QuarkPlatformPkg/QuarkCapsule.fdf
> |   82 ++
>  QuarkPlatformPkg/QuarkMin.dsc
> |    7 +-
>  SecurityPkg/Library/FmpAuthenticationPkcs7Lib/FmpAuthenticationPkcs7Lib.c
> |  144 ++
>  SecurityPkg/Library/FmpAuthenticationPkcs7Lib/FmpAuthenticationPkcs7Lib.inf
> |   52 +
>  SecurityPkg/Library/FmpAuthenticationPkcs7Lib/FmpAuthenticationPkcs7Lib.uni
> |   26 +
> 
> SecurityPkg/Library/FmpAuthenticationRsa2048Sha256Lib/FmpAuthenticationRsa2048Sha256L
> ib.c     |  286 ++++
> 
> SecurityPkg/Library/FmpAuthenticationRsa2048Sha256Lib/FmpAuthenticationRsa2048Sha256L
> ib.inf   |   53 +
> 
> SecurityPkg/Library/FmpAuthenticationRsa2048Sha256Lib/FmpAuthenticationRsa2048Sha256L
> ib.uni   |   26 +
>  SecurityPkg/SecurityPkg.dec
> |    6 +
>  SecurityPkg/SecurityPkg.dsc
> |    3 +
>  UefiCpuPkg/Application/MicrocodeCapsuleApp/AppSupport.c
> |  480 ++++++
>  UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.c
> |  283 ++++
>  UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.inf
> |   62 +
>  UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.uni
> |   22 +
>  UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleAppExtra.uni
> |   19 +
>  UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleDump.c
> |  171 +++
>  UefiCpuPkg/Include/Guid/MicrocodeFmp.h
> |   21 +
>  UefiCpuPkg/Include/Library/MicrocodeFlashAccessLib.h
> |   39 +
>  UefiCpuPkg/Library/MicrocodeFlashAccessLibNull/MicrocodeFlashAccessLibNull.c
> |   42 +
>  UefiCpuPkg/Library/MicrocodeFlashAccessLibNull/MicrocodeFlashAccessLibNull.inf
> |   40 +
>  UefiCpuPkg/Library/MicrocodeFlashAccessLibNull/MicrocodeFlashAccessLibNull.uni
> |   21 +
>  UefiCpuPkg/MicrocodeUpdate/MicrocodeFmp.c
> |  641 ++++++++
>  UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.c
> |  775 ++++++++++
>  UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.h
> |  299 ++++
>  UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.inf
> |   68 +
>  UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdateDxe.uni
> |   21 +
>  UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdateDxeExtra.uni
> |   20 +
>  UefiCpuPkg/UefiCpuPkg.dec
> |    7 +
>  UefiCpuPkg/UefiCpuPkg.dsc
> |    3 +
> 
> Vlv2TbltDevicePkg/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessL
> ib.c     |  192 +++
> 
> Vlv2TbltDevicePkg/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessL
> ib.inf   |   47 +
>  Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptor.aslc
> |   86 ++
>  Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptor.inf
> |   45 +
>  Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptorPei.c
> |   66 +
>  Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosUpdateConfig/SystemBiosUpdateConfig.ini
> |   72 +
> 
> Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosUpdateConfig/SystemBiosUpdateConfigGcc.in
> i        |   72 +
>  Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLib.c
> |  156 +-
>  Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLib.inf
> |    8 +-
>  Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLibDxe.c
> |   62 +
>  Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLibDxe.inf
> |   49 +
>  Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLibDxeRuntimeSmm.c
> |  188 +++
>  Vlv2TbltDevicePkg/Library/FlashDeviceLib/SpiChipDefinitions.h
> |    5 +-
>  Vlv2TbltDevicePkg/Library/PlatformBdsLib/BdsPlatform.c
> |  117 +-
>  Vlv2TbltDevicePkg/Library/PlatformBdsLib/PlatformBdsLib.inf
> |    2 +
>  Vlv2TbltDevicePkg/PlatformCapsule.dsc
> |   44 +
>  Vlv2TbltDevicePkg/PlatformCapsule.fdf
> |   81 ++
>  Vlv2TbltDevicePkg/PlatformCapsuleGcc.fdf
> |   81 ++
>  Vlv2TbltDevicePkg/PlatformPkg.fdf
> |  132 +-
>  Vlv2TbltDevicePkg/PlatformPkgConfig.dsc
> |    3 +-
>  Vlv2TbltDevicePkg/PlatformPkgGcc.fdf
> |  132 +-
>  Vlv2TbltDevicePkg/PlatformPkgGccX64.dsc
> |   70 +-
>  Vlv2TbltDevicePkg/PlatformPkgIA32.dsc
> |   70 +-
>  Vlv2TbltDevicePkg/PlatformPkgX64.dsc
> |   70 +-
>  Vlv2TbltDevicePkg/bld_vlv.bat
> |    8 +-
>  124 files changed, 17848 insertions(+), 384 deletions(-)
>  create mode 100644 MdeModulePkg/Application/CapsuleApp/AppSupport.c
>  create mode 100644 MdeModulePkg/Application/CapsuleApp/CapsuleApp.c
>  create mode 100644 MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf
>  create mode 100644 MdeModulePkg/Application/CapsuleApp/CapsuleApp.uni
>  create mode 100644 MdeModulePkg/Application/CapsuleApp/CapsuleAppExtra.uni
>  create mode 100644 MdeModulePkg/Application/CapsuleApp/CapsuleDump.c
>  create mode 100644 MdeModulePkg/Include/Guid/EdkiiSystemFmpCapsule.h
>  create mode 100644 MdeModulePkg/Include/Library/EdkiiSystemCapsuleLib.h
>  create mode 100644 MdeModulePkg/Include/Library/FmpAuthenticationLib.h
>  create mode 100644 MdeModulePkg/Include/Library/IniParsingLib.h
>  create mode 100644 MdeModulePkg/Include/Library/PlatformFlashAccessLib.h
>  create mode 100644 MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.c
>  create mode 100644 MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.inf
>  create mode 100644 MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.uni
>  create mode 100644 MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleProcessLib.c
>  create mode 100644 MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleReportLib.c
>  create mode 100644 MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleRuntime.c
>  create mode 100644 MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf
>  create mode 100644 MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.uni
>  create mode 100644
> MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.c
>  create mode 100644
> MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.inf
>  create mode 100644
> MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.uni
>  create mode 100644 MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.c
>  create mode 100644
> MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.inf
>  create mode 100644
> MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.uni
>  create mode 100644 MdeModulePkg/Library/IniParsingLib/IniParsingLib.c
>  create mode 100644 MdeModulePkg/Library/IniParsingLib/IniParsingLib.inf
>  create mode 100644 MdeModulePkg/Library/IniParsingLib/IniParsingLib.uni
>  create mode 100644
> MdeModulePkg/Library/PlatformFlashAccessLibNull/PlatformFlashAccessLibNull.c
>  create mode 100644
> MdeModulePkg/Library/PlatformFlashAccessLibNull/PlatformFlashAccessLibNull.inf
>  create mode 100644
> MdeModulePkg/Library/PlatformFlashAccessLibNull/PlatformFlashAccessLibNull.uni
>  create mode 100644 MdeModulePkg/Universal/RecoveryModuleLoadPei/ParseConfigProfile.c
>  create mode 100644
> MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPei.c
>  create mode 100644
> MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPei.h
>  create mode 100644
> MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPei.inf
>  create mode 100644
> MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPei.uni
>  create mode 100644
> MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPeiExtra.uni
>  create mode 100644 MdeModulePkg/Universal/SystemBiosUpdate/ParseConfigProfile.c
>  create mode 100644 MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosDxe.h
>  create mode 100644 MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosMainDxe.c
>  create mode 100644 MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosMainSetImage.c
>  create mode 100644
> MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosMainSetImageDummy.c
>  create mode 100644 MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxe.inf
>  create mode 100644 MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxe.uni
>  create mode 100644
> MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxeExtra.uni
>  create mode 100644 MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxe.inf
>  create mode 100644 MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxe.uni
>  create mode 100644
> MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxeExtra.uni
>  create mode 100644
> QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLi
> bDxe.c
>  create mode 100644
> QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLi
> bDxe.inf
>  create mode 100644
> QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/SpiFlashDevice.c
>  create mode 100644
> QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/SpiFlashDevice.h
>  create mode 100644
> QuarkPlatformPkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptor.aslc
>  create mode 100644
> QuarkPlatformPkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptor.inf
>  create mode 100644
> QuarkPlatformPkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptorPei.c
>  create mode 100644
> QuarkPlatformPkg/Feature/Capsule/SystemBiosUpdateConfig/SystemBiosUpdateConfig.ini
>  create mode 100644 QuarkPlatformPkg/QuarkCapsule.dsc
>  create mode 100644 QuarkPlatformPkg/QuarkCapsule.fdf
>  create mode 100644
> SecurityPkg/Library/FmpAuthenticationPkcs7Lib/FmpAuthenticationPkcs7Lib.c
>  create mode 100644
> SecurityPkg/Library/FmpAuthenticationPkcs7Lib/FmpAuthenticationPkcs7Lib.inf
>  create mode 100644
> SecurityPkg/Library/FmpAuthenticationPkcs7Lib/FmpAuthenticationPkcs7Lib.uni
>  create mode 100644
> SecurityPkg/Library/FmpAuthenticationRsa2048Sha256Lib/FmpAuthenticationRsa2048Sha256L
> ib.c
>  create mode 100644
> SecurityPkg/Library/FmpAuthenticationRsa2048Sha256Lib/FmpAuthenticationRsa2048Sha256L
> ib.inf
>  create mode 100644
> SecurityPkg/Library/FmpAuthenticationRsa2048Sha256Lib/FmpAuthenticationRsa2048Sha256L
> ib.uni
>  create mode 100644 UefiCpuPkg/Application/MicrocodeCapsuleApp/AppSupport.c
>  create mode 100644 UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.c
>  create mode 100644
> UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.inf
>  create mode 100644
> UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.uni
>  create mode 100644
> UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleAppExtra.uni
>  create mode 100644 UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleDump.c
>  create mode 100644 UefiCpuPkg/Include/Guid/MicrocodeFmp.h
>  create mode 100644 UefiCpuPkg/Include/Library/MicrocodeFlashAccessLib.h
>  create mode 100644
> UefiCpuPkg/Library/MicrocodeFlashAccessLibNull/MicrocodeFlashAccessLibNull.c
>  create mode 100644
> UefiCpuPkg/Library/MicrocodeFlashAccessLibNull/MicrocodeFlashAccessLibNull.inf
>  create mode 100644
> UefiCpuPkg/Library/MicrocodeFlashAccessLibNull/MicrocodeFlashAccessLibNull.uni
>  create mode 100644 UefiCpuPkg/MicrocodeUpdate/MicrocodeFmp.c
>  create mode 100644 UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.c
>  create mode 100644 UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.h
>  create mode 100644 UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.inf
>  create mode 100644 UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdateDxe.uni
>  create mode 100644 UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdateDxeExtra.uni
>  create mode 100644
> Vlv2TbltDevicePkg/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessL
> ib.c
>  create mode 100644
> Vlv2TbltDevicePkg/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessL
> ib.inf
>  create mode 100644
> Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptor.aslc
>  create mode 100644
> Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptor.inf
>  create mode 100644
> Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptorPei.c
>  create mode 100644
> Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosUpdateConfig/SystemBiosUpdateConfig.ini
>  create mode 100644
> Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosUpdateConfig/SystemBiosUpdateConfigGcc.in
> i
>  create mode 100644 Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLibDxe.c
>  create mode 100644 Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLibDxe.inf
>  create mode 100644
> Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLibDxeRuntimeSmm.c
>  create mode 100644 Vlv2TbltDevicePkg/PlatformCapsule.dsc
>  create mode 100644 Vlv2TbltDevicePkg/PlatformCapsule.fdf
>  create mode 100644 Vlv2TbltDevicePkg/PlatformCapsuleGcc.fdf
> 
> --
> 2.7.4.windows.1
> 
> _______________________________________________
> edk2-devel mailing list
> edk2-devel@lists.01.org
> https://lists.01.org/mailman/listinfo/edk2-devel


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

* Re: [PATCH 43/45] Vlv2TbltDevicePkg/dsc/fdf: Add capsule/recovery support.
  2016-09-21  6:45 ` [PATCH 43/45] Vlv2TbltDevicePkg/dsc/fdf: Add capsule/recovery support Jiewen Yao
@ 2016-09-22  1:36   ` Wei, David
  2016-09-22  1:39   ` Wei, David
  1 sibling, 0 replies; 83+ messages in thread
From: Wei, David @ 2016-09-22  1:36 UTC (permalink / raw)
  To: Yao, Jiewen, edk2-devel@lists.01.org
  Cc: Tian, Feng, Zeng, Star, Kinney, Michael D, Gao, Liming,
	Zhang, Chao B, Yao, Jiewen, Wei, David

Reviewed-by:  David Wei <david.wei@intel.com>

Thanks,
David  Wei                                 


-----Original Message-----
From: Yao, Jiewen 
Sent: Wednesday, September 21, 2016 2:45 PM
To: edk2-devel@lists.01.org
Cc: Wei, David <david.wei@intel.com>; Tian, Feng <feng.tian@intel.com>; Zeng, Star <star.zeng@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: [PATCH 43/45] Vlv2TbltDevicePkg/dsc/fdf: Add capsule/recovery support.

Add capsule and recovery support module in platform dsc and fdf.

Cc: David Wei <david.wei@intel.com>
Cc: Feng Tian <feng.tian@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Chao Zhang <chao.b.zhang@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
---
 Vlv2TbltDevicePkg/PlatformPkg.fdf       | 132 ++++++++++----------
 Vlv2TbltDevicePkg/PlatformPkgConfig.dsc |   3 +-
 Vlv2TbltDevicePkg/PlatformPkgGcc.fdf    | 132 ++++++++++----------
 Vlv2TbltDevicePkg/PlatformPkgGccX64.dsc |  70 ++++++++++-
 Vlv2TbltDevicePkg/PlatformPkgIA32.dsc   |  70 ++++++++++-
 Vlv2TbltDevicePkg/PlatformPkgX64.dsc    |  70 ++++++++++-
 6 files changed, 341 insertions(+), 136 deletions(-)

diff --git a/Vlv2TbltDevicePkg/PlatformPkg.fdf b/Vlv2TbltDevicePkg/PlatformPkg.fdf
index 93b4d2d..7a793bd 100644
--- a/Vlv2TbltDevicePkg/PlatformPkg.fdf
+++ b/Vlv2TbltDevicePkg/PlatformPkg.fdf
@@ -82,6 +82,9 @@ NumBlocks     = $(FLASH_NUM_BLOCKS)          #The number of blocks in 3Mb FLASH
 SET gPlatformModuleTokenSpaceGuid.PcdFlashAreaBaseAddress            = $(FLASH_AREA_BASE_ADDRESS)
 SET gPlatformModuleTokenSpaceGuid.PcdFlashAreaSize                   = $(FLASH_AREA_SIZE)
 
+SET gUefiCpuPkgTokenSpaceGuid.PcdCpuMicrocodePatchAddress = $(FLASH_REGION_VLVMICROCODE_BASE) + 0x60
+SET gUefiCpuPkgTokenSpaceGuid.PcdCpuMicrocodePatchRegionSize = $(FLASH_REGION_VLVMICROCODE_SIZE) - 0x60
+
 !if $(MINNOW2_FSP_BUILD) == TRUE
 # put below PCD value setting into dsc file
 #SET gFspWrapperTokenSpaceGuid.PcdCpuMicrocodePatchAddress                = $(FLASH_REGION_VLVMICROCODE_BASE)
@@ -242,6 +245,34 @@ FILE RAW = 197DB236-F856-4924-90F8-CDF12FB875F3 {
   $(OUTPUT_DIRECTORY)\$(TARGET)_$(TOOL_CHAIN_TAG)\$(DXE_ARCHITECTURE)\MicrocodeUpdates.bin
 }
 
+!if $(RECOVERY_ENABLE)
+[FV.FVRECOVERY_COMPONENTS]
+FvAlignment        = 16         #FV alignment and FV attributes setting.
+ERASE_POLARITY     = 1
+MEMORY_MAPPED      = TRUE
+STICKY_WRITE       = TRUE
+LOCK_CAP           = TRUE
+LOCK_STATUS        = TRUE
+WRITE_DISABLED_CAP = TRUE
+WRITE_ENABLED_CAP  = TRUE
+WRITE_STATUS       = TRUE
+WRITE_LOCK_CAP     = TRUE
+WRITE_LOCK_STATUS  = TRUE
+READ_DISABLED_CAP  = TRUE
+READ_ENABLED_CAP   = TRUE
+READ_STATUS        = TRUE
+READ_LOCK_CAP      = TRUE
+READ_LOCK_STATUS   = TRUE
+
+INF  RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/PchUsb.inf
+INF  MdeModulePkg/Bus/Pci/EhciPei/EhciPei.inf
+INF  MdeModulePkg/Bus/Usb/UsbBusPei/UsbBusPei.inf
+INF  MdeModulePkg/Bus/Usb/UsbBotPei/UsbBotPei.inf
+INF  FatPkg/FatPei/FatPei.inf
+INF  MdeModulePkg/Universal/Disk/CdExpressPei/CdExpressPei.inf
+INF  MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPei.inf
+!endif
+
 ################################################################################
 #
 # FV Section
@@ -306,6 +337,15 @@ INF MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf
 INF MdeModulePkg/Universal/ReportStatusCodeRouter/Pei/ReportStatusCodeRouterPei.inf
 !endif
 
+!if $(RECOVERY_ENABLE)
+FILE FV_IMAGE = 1E9D7604-EF45-46a0-BD8A-71AC78C17AC1 {
+  SECTION PEI_DEPEX_EXP = {gEfiPeiMemoryDiscoveredPpiGuid AND gEfiPeiBootInRecoveryModePpiGuid}
+  SECTION GUIDED EE4E5898-3914-4259-9D6E-DC7BD79403CF {    # LZMA COMPRESS GUID
+    SECTION FV_IMAGE = FVRECOVERY_COMPONENTS
+  }
+}
+!endif
+
 [FV.FVRECOVERY]
 BlockSize          = $(FLASH_BLOCK_SIZE)
 FvAlignment        = 16         #FV alignment and FV attributes setting.
@@ -373,6 +413,11 @@ INF RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET
 
 INF MdeModulePkg/Universal/PCD/Pei/Pcd.inf
 
+!if $(CAPSULE_ENABLE) || $(RECOVERY_ENABLE)
+  # FMP image decriptor
+INF RuleOverride = FMP_IMAGE_DESC Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptor.inf
+!endif
+
 [FV.FVMAIN]
 BlockSize          = $(FLASH_BLOCK_SIZE)
 FvAlignment        = 16
@@ -717,6 +762,12 @@ FILE FREEFORM = 878AC2CC-5343-46F2-B563-51F89DAF56BA {
   !endif
 !endif
 
+!if $(CAPSULE_ENABLE)
+INF  MdeModulePkg/Universal/EsrtDxe/EsrtDxe.inf
+INF  MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxe.inf
+INF  UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.inf
+!endif
+
 [FV.FVMAIN_COMPACT]
 BlockSize          = $(FLASH_BLOCK_SIZE)
 FvAlignment        = 16
@@ -780,8 +831,8 @@ READ_LOCK_CAP      = TRUE
 READ_LOCK_STATUS   = TRUE
 
 
-[FV.Update_Data]
-BlockSize          = $(FLASH_BLOCK_SIZE)
+!if $(CAPSULE_ENABLE) || $(RECOVERY_ENABLE)
+[FV.CapsuleDispatchFv]
 FvAlignment        = 16
 ERASE_POLARITY     = 1
 MEMORY_MAPPED      = TRUE
@@ -799,71 +850,11 @@ READ_STATUS        = TRUE
 READ_LOCK_CAP      = TRUE
 READ_LOCK_STATUS   = TRUE
 
-FILE RAW = 88888888-8888-8888-8888-888888888888 {
-       FD = Vlv
-     }
-
-[FV.BiosUpdateCargo]
-BlockSize          = $(FLASH_BLOCK_SIZE)
-FvAlignment        = 16
-ERASE_POLARITY     = 1
-MEMORY_MAPPED      = TRUE
-STICKY_WRITE       = TRUE
-LOCK_CAP           = TRUE
-LOCK_STATUS        = TRUE
-WRITE_DISABLED_CAP = TRUE
-WRITE_ENABLED_CAP  = TRUE
-WRITE_STATUS       = TRUE
-WRITE_LOCK_CAP     = TRUE
-WRITE_LOCK_STATUS  = TRUE
-READ_DISABLED_CAP  = TRUE
-READ_ENABLED_CAP   = TRUE
-READ_STATUS        = TRUE
-READ_LOCK_CAP      = TRUE
-READ_LOCK_STATUS   = TRUE
-
-
-
-[FV.BiosUpdate]
-BlockSize          = $(FLASH_BLOCK_SIZE)
-FvAlignment        = 16
-ERASE_POLARITY     = 1
-MEMORY_MAPPED      = TRUE
-STICKY_WRITE       = TRUE
-LOCK_CAP           = TRUE
-LOCK_STATUS        = TRUE
-WRITE_DISABLED_CAP = TRUE
-WRITE_ENABLED_CAP  = TRUE
-WRITE_STATUS       = TRUE
-WRITE_LOCK_CAP     = TRUE
-WRITE_LOCK_STATUS  = TRUE
-READ_DISABLED_CAP  = TRUE
-READ_ENABLED_CAP   = TRUE
-READ_STATUS        = TRUE
-READ_LOCK_CAP      = TRUE
-READ_LOCK_STATUS   = TRUE
-
-[Capsule.Capsule_Boot]
-#
-# gEfiCapsuleGuid supported by platform
-# { 0x3B6686BD, 0x0D76, 0x4030, { 0xB7, 0x0E, 0xB5, 0x51, 0x9E, 0x2F, 0xC5, 0xA0 }}
-#
-CAPSULE_GUID  = 3B6686BD-0D76-4030-B70E-B5519E2FC5A0
-CAPSULE_FLAGS = PersistAcrossReset
-CAPSULE_HEADER_SIZE = 0x20
-
-FV = BiosUpdate
-
-[Capsule.Capsule_Reset]
-#
-# gEfiCapsuleGuid supported by platform
-# { 0x3B6686BD, 0x0D76, 0x4030, { 0xB7, 0x0E, 0xB5, 0x51, 0x9E, 0x2F, 0xC5, 0xA0 }}
-#
-CAPSULE_GUID  = 3B6686BD-0D76-4030-B70E-B5519E2FC5A0
-CAPSULE_FLAGS = PersistAcrossReset
-CAPSULE_HEADER_SIZE = 0x20
+!if $(CAPSULE_ENABLE)
+INF  MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxe.inf
+!endif
 
-FV = BiosUpdate
+!endif
 
 ################################################################################
 #
@@ -1089,3 +1080,12 @@ FV = BiosUpdate
     RAW ASL   Optional            |.aml
   }
 
+[Rule.Common.PEIM.FMP_IMAGE_DESC]
+  FILE PEIM = $(NAMED_GUID) {
+     RAW BIN                  |.acpi
+     PEI_DEPEX PEI_DEPEX Optional        $(INF_OUTPUT)/$(MODULE_NAME).depex
+     PE32      PE32    Align=4K          $(INF_OUTPUT)/$(MODULE_NAME).efi
+     UI       STRING="$(MODULE_NAME)" Optional
+     VERSION  STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+  }
+
diff --git a/Vlv2TbltDevicePkg/PlatformPkgConfig.dsc b/Vlv2TbltDevicePkg/PlatformPkgConfig.dsc
index db50b93..a6af8a1 100644
--- a/Vlv2TbltDevicePkg/PlatformPkgConfig.dsc
+++ b/Vlv2TbltDevicePkg/PlatformPkgConfig.dsc
@@ -1,7 +1,7 @@
 #/** @file
 # platform configuration file.
 #
-# Copyright (c) 2012  - 2015, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2012  - 2016, Intel Corporation. All rights reserved.<BR>
 #                                                                                  

 # This program and the accompanying materials are licensed and made available under

 # the terms and conditions of the BSD License that accompanies this distribution.  

@@ -65,6 +65,7 @@ DEFINE VARIABLE_INFO_ENABLE = FALSE
 DEFINE S3_ENABLE = TRUE
 DEFINE CAPSULE_ENABLE = FALSE
 DEFINE CAPSULE_RESET_ENABLE = TRUE
+DEFINE RECOVERY_ENABLE = FALSE
 
 DEFINE GOP_DRIVER_ENABLE = TRUE
 DEFINE DATAHUB_ENABLE = TRUE
diff --git a/Vlv2TbltDevicePkg/PlatformPkgGcc.fdf b/Vlv2TbltDevicePkg/PlatformPkgGcc.fdf
index 33f2038..4dfc09d 100644
--- a/Vlv2TbltDevicePkg/PlatformPkgGcc.fdf
+++ b/Vlv2TbltDevicePkg/PlatformPkgGcc.fdf
@@ -82,6 +82,9 @@ NumBlocks     = $(FLASH_NUM_BLOCKS)          #The number of blocks in 3Mb FLASH
 SET gPlatformModuleTokenSpaceGuid.PcdFlashAreaBaseAddress            = $(FLASH_AREA_BASE_ADDRESS)
 SET gPlatformModuleTokenSpaceGuid.PcdFlashAreaSize                   = $(FLASH_AREA_SIZE)
 
+SET gUefiCpuPkgTokenSpaceGuid.PcdCpuMicrocodePatchAddress = $(FLASH_REGION_VLVMICROCODE_BASE) + 0x60
+SET gUefiCpuPkgTokenSpaceGuid.PcdCpuMicrocodePatchRegionSize = $(FLASH_REGION_VLVMICROCODE_SIZE) - 0x60
+
 !if $(MINNOW2_FSP_BUILD) == TRUE
 # put below PCD value setting into dsc file
 #SET gFspWrapperTokenSpaceGuid.PcdCpuMicrocodePatchAddress                = $(FLASH_REGION_VLVMICROCODE_BASE)
@@ -199,6 +202,34 @@ FILE RAW = 197DB236-F856-4924-90F8-CDF12FB875F3 {
   $(OUTPUT_DIRECTORY)/$(TARGET)_$(TOOL_CHAIN_TAG)/$(DXE_ARCHITECTURE)/MicrocodeUpdates.bin
 }
 
+!if $(RECOVERY_ENABLE) == TRUE
+[FV.FVRECOVERY_COMPONENTS]
+FvAlignment        = 16         #FV alignment and FV attributes setting.
+ERASE_POLARITY     = 1
+MEMORY_MAPPED      = TRUE
+STICKY_WRITE       = TRUE
+LOCK_CAP           = TRUE
+LOCK_STATUS        = TRUE
+WRITE_DISABLED_CAP = TRUE
+WRITE_ENABLED_CAP  = TRUE
+WRITE_STATUS       = TRUE
+WRITE_LOCK_CAP     = TRUE
+WRITE_LOCK_STATUS  = TRUE
+READ_DISABLED_CAP  = TRUE
+READ_ENABLED_CAP   = TRUE
+READ_STATUS        = TRUE
+READ_LOCK_CAP      = TRUE
+READ_LOCK_STATUS   = TRUE
+
+INF  RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/PchUsb.inf
+INF  MdeModulePkg/Bus/Pci/EhciPei/EhciPei.inf
+INF  MdeModulePkg/Bus/Usb/UsbBusPei/UsbBusPei.inf
+INF  MdeModulePkg/Bus/Usb/UsbBotPei/UsbBotPei.inf
+INF  FatPkg/FatPei/FatPei.inf
+INF  MdeModulePkg/Universal/Disk/CdExpressPei/CdExpressPei.inf
+INF  MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPei.inf
+!endif
+
 ################################################################################
 #
 # FV Section
@@ -263,6 +294,15 @@ INF MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf
 INF MdeModulePkg/Universal/ReportStatusCodeRouter/Pei/ReportStatusCodeRouterPei.inf
 !endif
 
+!if $(RECOVERY_ENABLE)
+FILE FV_IMAGE = 1E9D7604-EF45-46a0-BD8A-71AC78C17AC1 {
+  SECTION PEI_DEPEX_EXP = {gEfiPeiMemoryDiscoveredPpiGuid AND gEfiPeiBootInRecoveryModePpiGuid}
+  SECTION GUIDED EE4E5898-3914-4259-9D6E-DC7BD79403CF {    # LZMA COMPRESS GUID
+    SECTION FV_IMAGE = FVRECOVERY_COMPONENTS
+  }
+}
+!endif
+
 [FV.FVRECOVERY]
 BlockSize          = $(FLASH_BLOCK_SIZE)
 FvAlignment        = 16         #FV alignment and FV attributes setting.
@@ -330,6 +370,11 @@ INF RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET
 
 INF MdeModulePkg/Universal/PCD/Pei/Pcd.inf
 
+!if $(CAPSULE_ENABLE) || $(RECOVERY_ENABLE)
+  # FMP image decriptor
+INF RuleOverride = FMP_IMAGE_DESC Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptor.inf
+!endif
+
 [FV.FVMAIN]
 BlockSize          = $(FLASH_BLOCK_SIZE)
 FvAlignment        = 16
@@ -674,6 +719,12 @@ FILE FREEFORM = 878AC2CC-5343-46F2-B563-51F89DAF56BA {
   !endif
 !endif
 
+!if $(CAPSULE_ENABLE)
+INF  MdeModulePkg/Universal/EsrtDxe/EsrtDxe.inf
+INF  MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxe.inf
+INF  UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.inf
+!endif
+
 [FV.FVMAIN_COMPACT]
 BlockSize          = $(FLASH_BLOCK_SIZE)
 FvAlignment        = 16
@@ -737,8 +788,8 @@ READ_LOCK_CAP      = TRUE
 READ_LOCK_STATUS   = TRUE
 
 
-[FV.Update_Data]
-BlockSize          = $(FLASH_BLOCK_SIZE)
+!if $(CAPSULE_ENABLE) || $(RECOVERY_ENABLE)
+[FV.CapsuleDispatchFv]
 FvAlignment        = 16
 ERASE_POLARITY     = 1
 MEMORY_MAPPED      = TRUE
@@ -756,71 +807,11 @@ READ_STATUS        = TRUE
 READ_LOCK_CAP      = TRUE
 READ_LOCK_STATUS   = TRUE
 
-FILE RAW = 88888888-8888-8888-8888-888888888888 {
-       FD = Vlv
-     }
-
-[FV.BiosUpdateCargo]
-BlockSize          = $(FLASH_BLOCK_SIZE)
-FvAlignment        = 16
-ERASE_POLARITY     = 1
-MEMORY_MAPPED      = TRUE
-STICKY_WRITE       = TRUE
-LOCK_CAP           = TRUE
-LOCK_STATUS        = TRUE
-WRITE_DISABLED_CAP = TRUE
-WRITE_ENABLED_CAP  = TRUE
-WRITE_STATUS       = TRUE
-WRITE_LOCK_CAP     = TRUE
-WRITE_LOCK_STATUS  = TRUE
-READ_DISABLED_CAP  = TRUE
-READ_ENABLED_CAP   = TRUE
-READ_STATUS        = TRUE
-READ_LOCK_CAP      = TRUE
-READ_LOCK_STATUS   = TRUE
-
-
-
-[FV.BiosUpdate]
-BlockSize          = $(FLASH_BLOCK_SIZE)
-FvAlignment        = 16
-ERASE_POLARITY     = 1
-MEMORY_MAPPED      = TRUE
-STICKY_WRITE       = TRUE
-LOCK_CAP           = TRUE
-LOCK_STATUS        = TRUE
-WRITE_DISABLED_CAP = TRUE
-WRITE_ENABLED_CAP  = TRUE
-WRITE_STATUS       = TRUE
-WRITE_LOCK_CAP     = TRUE
-WRITE_LOCK_STATUS  = TRUE
-READ_DISABLED_CAP  = TRUE
-READ_ENABLED_CAP   = TRUE
-READ_STATUS        = TRUE
-READ_LOCK_CAP      = TRUE
-READ_LOCK_STATUS   = TRUE
-
-[Capsule.Capsule_Boot]
-#
-# gEfiCapsuleGuid supported by platform
-# { 0x3B6686BD, 0x0D76, 0x4030, { 0xB7, 0x0E, 0xB5, 0x51, 0x9E, 0x2F, 0xC5, 0xA0 }}
-#
-CAPSULE_GUID  = 3B6686BD-0D76-4030-B70E-B5519E2FC5A0
-CAPSULE_FLAGS = PersistAcrossReset
-CAPSULE_HEADER_SIZE = 0x20
-
-FV = BiosUpdate
-
-[Capsule.Capsule_Reset]
-#
-# gEfiCapsuleGuid supported by platform
-# { 0x3B6686BD, 0x0D76, 0x4030, { 0xB7, 0x0E, 0xB5, 0x51, 0x9E, 0x2F, 0xC5, 0xA0 }}
-#
-CAPSULE_GUID  = 3B6686BD-0D76-4030-B70E-B5519E2FC5A0
-CAPSULE_FLAGS = PersistAcrossReset
-CAPSULE_HEADER_SIZE = 0x20
+!if $(CAPSULE_ENABLE)
+INF  MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxe.inf
+!endif
 
-FV = BiosUpdate
+!endif
 
 ################################################################################
 #
@@ -1050,3 +1041,12 @@ FV = BiosUpdate
     RAW ASL   Optional            |.aml
   }
 
+[Rule.Common.PEIM.FMP_IMAGE_DESC]
+  FILE PEIM = $(NAMED_GUID) {
+     RAW BIN                  |.acpi
+     PEI_DEPEX PEI_DEPEX Optional        $(INF_OUTPUT)/$(MODULE_NAME).depex
+     PE32      PE32    Align=4K          $(INF_OUTPUT)/$(MODULE_NAME).efi
+     UI       STRING="$(MODULE_NAME)" Optional
+     VERSION  STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+  }
+
diff --git a/Vlv2TbltDevicePkg/PlatformPkgGccX64.dsc b/Vlv2TbltDevicePkg/PlatformPkgGccX64.dsc
index 7125366..47bb23e 100644
--- a/Vlv2TbltDevicePkg/PlatformPkgGccX64.dsc
+++ b/Vlv2TbltDevicePkg/PlatformPkgGccX64.dsc
@@ -183,10 +183,15 @@
 
   OemHookStatusCodeLib|MdeModulePkg/Library/OemHookStatusCodeLibNull/OemHookStatusCodeLibNull.inf
 !if $(CAPSULE_ENABLE) == TRUE
- CapsuleLib|IntelFrameworkModulePkg/Library/DxeCapsuleLib/DxeCapsuleLib.inf
+  CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.inf
 !else
   CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf
 !endif
+  EdkiiSystemCapsuleLib|MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.inf
+  FmpAuthenticationLib|MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.inf
+  IniParsingLib|MdeModulePkg/Library/IniParsingLib/IniParsingLib.inf
+  PlatformFlashAccessLib|Vlv2TbltDevicePkg/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.inf
+  MicrocodeFlashAccessLib|Vlv2TbltDevicePkg/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.inf
   LanguageLib|EdkCompatibilityPkg/Compatibility/Library/UefiLanguageLib/UefiLanguageLib.inf
   SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
   SecurityManagementLib|MdeModulePkg/Library/DxeSecurityManagementLib/DxeSecurityManagementLib.inf
@@ -381,6 +386,8 @@
   DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgentLib.inf
 !endif
 
+  FlashDeviceLib|$(PLATFORM_PACKAGE)/Library/FlashDeviceLib/FlashDeviceLibDxe.inf
+
 [LibraryClasses.X64.DXE_CORE]
   HobLib|MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.inf
   MemoryAllocationLib|MdeModulePkg/Library/DxeCoreMemoryAllocationLib/DxeCoreMemoryAllocationLib.inf
@@ -450,6 +457,10 @@
   DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgentLib.inf
 !endif
 
+!if $(CAPSULE_ENABLE)
+  CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf
+!endif
+
 [LibraryClasses.common.UEFI_DRIVER]
   PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
 
@@ -886,6 +897,11 @@
   gEfiVLVTokenSpaceGuid.PcdCpuSmramCpuDataAddress|0
   gEfiVLVTokenSpaceGuid.PcdCpuLockBoxSize|0
 
+!if $(CAPSULE_ENABLE) || $(RECOVERY_ENABLE)
+  gEfiMdeModulePkgTokenSpaceGuid.PcdEdkiiSystemFmpCapsuleImageTypeIdGuid|{0x7b, 0x26, 0x96, 0x40, 0x0a, 0xda, 0xeb, 0x42, 0xb5, 0xeb, 0xfe, 0xf3, 0x1d, 0x20, 0x7c, 0xb4}
+  gEfiMdeModulePkgTokenSpaceGuid.PcdEdkiiSystemFirmwareImageDescriptor|{0x0}|VOID*|0x100
+!endif
+
 [Components.IA32]
 
   $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/SecCore.inf
@@ -907,6 +923,14 @@
   }
   !endif
 
+!if $(CAPSULE_ENABLE) || $(RECOVERY_ENABLE)
+  # FMP image decriptor
+  Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptor.inf {
+    <LibraryClasses>
+      PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf
+  }
+!endif
+
   MdeModulePkg/Core/Pei/PeiMain.inf {
 !if $(TARGET) == DEBUG
     <PcdsFixedAtBuild>
@@ -1011,6 +1035,24 @@ $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/fTPMInitPeim.inf
   $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/MpS3.inf
   EdkCompatibilityPkg/Compatibility/AcpiVariableHobOnSmramReserveHobThunk/AcpiVariableHobOnSmramReserveHobThunk.inf
   $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/PiSmmCommunicationPei.inf
+
+!if $(RECOVERY_ENABLE)
+  #
+  # Recovery
+  #
+  $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/PchUsb.inf
+  MdeModulePkg/Bus/Pci/EhciPei/EhciPei.inf
+  MdeModulePkg/Bus/Usb/UsbBusPei/UsbBusPei.inf
+  MdeModulePkg/Bus/Usb/UsbBotPei/UsbBotPei.inf
+  FatPkg/FatPei/FatPei.inf
+  MdeModulePkg/Universal/Disk/CdExpressPei/CdExpressPei.inf
+  MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPei.inf {
+    <LibraryClasses>
+      NULL|SecurityPkg/Library/FmpAuthenticationRsa2048Sha256Lib/FmpAuthenticationRsa2048Sha256Lib.inf
+      PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf
+  }
+!endif
+
 !if $(CAPSULE_ENABLE) == TRUE
   MdeModulePkg/Universal/CapsulePei/CapsulePei.inf
 !endif
@@ -1146,6 +1188,9 @@ $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/fTPMInitPeim.inf
       DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
       PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
       SerialPortLib|$(PLATFORM_PACKAGE)/Library/SerialPortLib/SerialPortLib.inf
+!if $(CAPSULE_ENABLE) == TRUE
+      NULL|SecurityPkg/Library/FmpAuthenticationPkcs7Lib/FmpAuthenticationPkcs7Lib.inf
+!endif
     !if $(FTPM_ENABLE) == TRUE
       Tpm2DeviceLib|Vlv2TbltDevicePkg/Library/Tpm2DeviceLibSeCDxe/Tpm2DeviceLibSeC.inf
     !else
@@ -1518,6 +1563,29 @@ $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/fTPMInitPeim.inf
 
   Vlv2TbltDevicePkg/Application/FirmwareUpdate/FirmwareUpdate.inf
 
+!if $(CAPSULE_ENABLE)
+  MdeModulePkg/Universal/EsrtDxe/EsrtDxe.inf
+
+  MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxe.inf
+  MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxe.inf {
+    <LibraryClasses>
+      DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
+      PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
+      SerialPortLib|$(PLATFORM_PACKAGE)/Library/SerialPortLib/SerialPortLib.inf
+      NULL|SecurityPkg/Library/FmpAuthenticationPkcs7Lib/FmpAuthenticationPkcs7Lib.inf
+  }
+  MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf
+
+  UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.inf {
+    <LibraryClasses>
+      DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
+      PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
+      SerialPortLib|$(PLATFORM_PACKAGE)/Library/SerialPortLib/SerialPortLib.inf
+  }
+  UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.inf
+
+!endif
+
 [BuildOptions]
 #
 # Define Build Options both for EDK and EDKII drivers.
diff --git a/Vlv2TbltDevicePkg/PlatformPkgIA32.dsc b/Vlv2TbltDevicePkg/PlatformPkgIA32.dsc
index 6efaf32..5f46793 100644
--- a/Vlv2TbltDevicePkg/PlatformPkgIA32.dsc
+++ b/Vlv2TbltDevicePkg/PlatformPkgIA32.dsc
@@ -183,10 +183,15 @@
 
   OemHookStatusCodeLib|MdeModulePkg/Library/OemHookStatusCodeLibNull/OemHookStatusCodeLibNull.inf
 !if $(CAPSULE_ENABLE) == TRUE
- CapsuleLib|IntelFrameworkModulePkg/Library/DxeCapsuleLib/DxeCapsuleLib.inf
+  CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.inf
 !else
   CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf
 !endif
+  EdkiiSystemCapsuleLib|MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.inf
+  FmpAuthenticationLib|MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.inf
+  IniParsingLib|MdeModulePkg/Library/IniParsingLib/IniParsingLib.inf
+  PlatformFlashAccessLib|Vlv2TbltDevicePkg/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.inf
+  MicrocodeFlashAccessLib|Vlv2TbltDevicePkg/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.inf
   LanguageLib|EdkCompatibilityPkg/Compatibility/Library/UefiLanguageLib/UefiLanguageLib.inf
   SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
   SecurityManagementLib|MdeModulePkg/Library/DxeSecurityManagementLib/DxeSecurityManagementLib.inf
@@ -381,6 +386,8 @@
   DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgentLib.inf
 !endif
 
+  FlashDeviceLib|$(PLATFORM_PACKAGE)/Library/FlashDeviceLib/FlashDeviceLibDxe.inf
+
 [LibraryClasses.IA32.DXE_CORE]
   HobLib|MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.inf
   MemoryAllocationLib|MdeModulePkg/Library/DxeCoreMemoryAllocationLib/DxeCoreMemoryAllocationLib.inf
@@ -450,6 +457,10 @@
   DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgentLib.inf
 !endif
 
+!if $(CAPSULE_ENABLE) == TRUE
+  CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf
+!endif
+
 [LibraryClasses.common.UEFI_DRIVER]
   PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
 
@@ -888,6 +899,11 @@
   gEfiVLVTokenSpaceGuid.PcdCpuSmramCpuDataAddress|0
   gEfiVLVTokenSpaceGuid.PcdCpuLockBoxSize|0
 
+!if $(CAPSULE_ENABLE) || $(RECOVERY_ENABLE)
+  gEfiMdeModulePkgTokenSpaceGuid.PcdEdkiiSystemFmpCapsuleImageTypeIdGuid|{0x7b, 0x26, 0x96, 0x40, 0x0a, 0xda, 0xeb, 0x42, 0xb5, 0xeb, 0xfe, 0xf3, 0x1d, 0x20, 0x7c, 0xb4}
+  gEfiMdeModulePkgTokenSpaceGuid.PcdEdkiiSystemFirmwareImageDescriptor|{0x0}|VOID*|0x100
+!endif
+
 [Components.IA32]
 
   $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/SecCore.inf
@@ -909,6 +925,14 @@
   }
   !endif
 
+!if $(CAPSULE_ENABLE) || $(RECOVERY_ENABLE)
+  # FMP image decriptor
+  Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptor.inf {
+    <LibraryClasses>
+      PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf
+  }
+!endif
+
   MdeModulePkg/Core/Pei/PeiMain.inf {
 !if $(TARGET) == DEBUG
     <PcdsFixedAtBuild>
@@ -1008,6 +1032,24 @@ $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/fTPMInitPeim.inf
   $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/MpS3.inf
   EdkCompatibilityPkg/Compatibility/AcpiVariableHobOnSmramReserveHobThunk/AcpiVariableHobOnSmramReserveHobThunk.inf
   $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/PiSmmCommunicationPei.inf
+
+!if $(RECOVERY_ENABLE)
+  #
+  # Recovery
+  #
+  $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/PchUsb.inf
+  MdeModulePkg/Bus/Pci/EhciPei/EhciPei.inf
+  MdeModulePkg/Bus/Usb/UsbBusPei/UsbBusPei.inf
+  MdeModulePkg/Bus/Usb/UsbBotPei/UsbBotPei.inf
+  FatPkg/FatPei/FatPei.inf
+  MdeModulePkg/Universal/Disk/CdExpressPei/CdExpressPei.inf
+  MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPei.inf {
+    <LibraryClasses>
+      NULL|SecurityPkg/Library/FmpAuthenticationRsa2048Sha256Lib/FmpAuthenticationRsa2048Sha256Lib.inf
+      PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf
+  }
+!endif
+
 !if $(CAPSULE_ENABLE) == TRUE
   MdeModulePkg/Universal/CapsulePei/CapsulePei.inf
 !endif
@@ -1133,6 +1175,9 @@ $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/fTPMInitPeim.inf
       DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
       PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
       SerialPortLib|$(PLATFORM_PACKAGE)/Library/SerialPortLib/SerialPortLib.inf
+!if $(CAPSULE_ENABLE)
+      NULL|SecurityPkg/Library/FmpAuthenticationPkcs7Lib/FmpAuthenticationPkcs7Lib.inf
+!endif
     !if $(FTPM_ENABLE) == TRUE
       Tpm2DeviceLib|Vlv2TbltDevicePkg/Library/Tpm2DeviceLibSeCDxe/Tpm2DeviceLibSeC.inf
     !else
@@ -1499,6 +1544,29 @@ $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/fTPMInitPeim.inf
 
   Vlv2TbltDevicePkg/Application/FirmwareUpdate/FirmwareUpdate.inf
 
+!if $(CAPSULE_ENABLE)
+  MdeModulePkg/Universal/EsrtDxe/EsrtDxe.inf
+
+  MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxe.inf
+  MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxe.inf {
+    <LibraryClasses>
+      DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
+      PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
+      SerialPortLib|$(PLATFORM_PACKAGE)/Library/SerialPortLib/SerialPortLib.inf
+      NULL|SecurityPkg/Library/FmpAuthenticationPkcs7Lib/FmpAuthenticationPkcs7Lib.inf
+  }
+  MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf
+
+  UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.inf {
+    <LibraryClasses>
+      DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
+      PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
+      SerialPortLib|$(PLATFORM_PACKAGE)/Library/SerialPortLib/SerialPortLib.inf
+  }
+  UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.inf
+
+!endif
+
 [BuildOptions]
 #
 # Define Build Options both for EDK and EDKII drivers.
diff --git a/Vlv2TbltDevicePkg/PlatformPkgX64.dsc b/Vlv2TbltDevicePkg/PlatformPkgX64.dsc
index 6bb503d..b2ac048 100644
--- a/Vlv2TbltDevicePkg/PlatformPkgX64.dsc
+++ b/Vlv2TbltDevicePkg/PlatformPkgX64.dsc
@@ -183,10 +183,15 @@
 
   OemHookStatusCodeLib|MdeModulePkg/Library/OemHookStatusCodeLibNull/OemHookStatusCodeLibNull.inf
 !if $(CAPSULE_ENABLE) == TRUE
- CapsuleLib|IntelFrameworkModulePkg/Library/DxeCapsuleLib/DxeCapsuleLib.inf
+  CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.inf
 !else
   CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf
 !endif
+  EdkiiSystemCapsuleLib|MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.inf
+  FmpAuthenticationLib|MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.inf
+  IniParsingLib|MdeModulePkg/Library/IniParsingLib/IniParsingLib.inf
+  PlatformFlashAccessLib|Vlv2TbltDevicePkg/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.inf
+  MicrocodeFlashAccessLib|Vlv2TbltDevicePkg/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.inf
   LanguageLib|EdkCompatibilityPkg/Compatibility/Library/UefiLanguageLib/UefiLanguageLib.inf
   SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
   SecurityManagementLib|MdeModulePkg/Library/DxeSecurityManagementLib/DxeSecurityManagementLib.inf
@@ -381,6 +386,8 @@
   DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgentLib.inf
 !endif
 
+  FlashDeviceLib|$(PLATFORM_PACKAGE)/Library/FlashDeviceLib/FlashDeviceLibDxe.inf
+
 [LibraryClasses.X64.DXE_CORE]
   HobLib|MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.inf
   MemoryAllocationLib|MdeModulePkg/Library/DxeCoreMemoryAllocationLib/DxeCoreMemoryAllocationLib.inf
@@ -450,6 +457,10 @@
   DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgentLib.inf
 !endif
 
+!if $(CAPSULE_ENABLE)
+  CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf
+!endif
+
 [LibraryClasses.common.UEFI_DRIVER]
   PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
 
@@ -885,6 +896,11 @@
   gEfiVLVTokenSpaceGuid.PcdCpuSmramCpuDataAddress|0
   gEfiVLVTokenSpaceGuid.PcdCpuLockBoxSize|0
 
+!if $(CAPSULE_ENABLE) || $(RECOVERY_ENABLE)
+  gEfiMdeModulePkgTokenSpaceGuid.PcdEdkiiSystemFmpCapsuleImageTypeIdGuid|{0x7b, 0x26, 0x96, 0x40, 0x0a, 0xda, 0xeb, 0x42, 0xb5, 0xeb, 0xfe, 0xf3, 0x1d, 0x20, 0x7c, 0xb4}
+  gEfiMdeModulePkgTokenSpaceGuid.PcdEdkiiSystemFirmwareImageDescriptor|{0x0}|VOID*|0x100
+!endif
+
 [Components.IA32]
 
   $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/SecCore.inf
@@ -906,6 +922,14 @@
   }
   !endif
 
+!if $(CAPSULE_ENABLE) || $(RECOVERY_ENABLE)
+  # FMP image decriptor
+  Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptor.inf {
+    <LibraryClasses>
+      PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf
+  }
+!endif
+
   MdeModulePkg/Core/Pei/PeiMain.inf {
 !if $(TARGET) == DEBUG
     <PcdsFixedAtBuild>
@@ -1005,6 +1029,24 @@ $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/fTPMInitPeim.inf
   $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/MpS3.inf
   EdkCompatibilityPkg/Compatibility/AcpiVariableHobOnSmramReserveHobThunk/AcpiVariableHobOnSmramReserveHobThunk.inf
   $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/PiSmmCommunicationPei.inf
+
+!if $(RECOVERY_ENABLE)
+  #
+  # Recovery
+  #
+  $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/PchUsb.inf
+  MdeModulePkg/Bus/Pci/EhciPei/EhciPei.inf
+  MdeModulePkg/Bus/Usb/UsbBusPei/UsbBusPei.inf
+  MdeModulePkg/Bus/Usb/UsbBotPei/UsbBotPei.inf
+  FatPkg/FatPei/FatPei.inf
+  MdeModulePkg/Universal/Disk/CdExpressPei/CdExpressPei.inf
+  MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPei.inf {
+    <LibraryClasses>
+      NULL|SecurityPkg/Library/FmpAuthenticationRsa2048Sha256Lib/FmpAuthenticationRsa2048Sha256Lib.inf
+      PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf
+  }
+!endif
+
 !if $(CAPSULE_ENABLE) == TRUE
   MdeModulePkg/Universal/CapsulePei/CapsulePei.inf
 !endif
@@ -1139,6 +1181,9 @@ $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/fTPMInitPeim.inf
       DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
       PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
       SerialPortLib|$(PLATFORM_PACKAGE)/Library/SerialPortLib/SerialPortLib.inf
+!if $(CAPSULE_ENABLE)
+      NULL|SecurityPkg/Library/FmpAuthenticationPkcs7Lib/FmpAuthenticationPkcs7Lib.inf
+!endif
     !if $(FTPM_ENABLE) == TRUE
       Tpm2DeviceLib|Vlv2TbltDevicePkg/Library/Tpm2DeviceLibSeCDxe/Tpm2DeviceLibSeC.inf
     !else
@@ -1505,6 +1550,29 @@ $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/fTPMInitPeim.inf
 
   Vlv2TbltDevicePkg/Application/FirmwareUpdate/FirmwareUpdate.inf
 
+!if $(CAPSULE_ENABLE)
+  MdeModulePkg/Universal/EsrtDxe/EsrtDxe.inf
+
+  MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxe.inf
+  MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxe.inf {
+    <LibraryClasses>
+      DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
+      PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
+      SerialPortLib|$(PLATFORM_PACKAGE)/Library/SerialPortLib/SerialPortLib.inf
+      NULL|SecurityPkg/Library/FmpAuthenticationPkcs7Lib/FmpAuthenticationPkcs7Lib.inf
+  }
+  MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf
+
+  UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.inf {
+    <LibraryClasses>
+      DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
+      PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
+      SerialPortLib|$(PLATFORM_PACKAGE)/Library/SerialPortLib/SerialPortLib.inf
+  }
+  UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.inf
+
+!endif
+
 [BuildOptions]
 #
 # Define Build Options both for EDK and EDKII drivers.
-- 
2.7.4.windows.1



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

* Re: [PATCH 43/45] Vlv2TbltDevicePkg/dsc/fdf: Add capsule/recovery support.
  2016-09-21  6:45 ` [PATCH 43/45] Vlv2TbltDevicePkg/dsc/fdf: Add capsule/recovery support Jiewen Yao
  2016-09-22  1:36   ` Wei, David
@ 2016-09-22  1:39   ` Wei, David
  1 sibling, 0 replies; 83+ messages in thread
From: Wei, David @ 2016-09-22  1:39 UTC (permalink / raw)
  To: Yao, Jiewen, edk2-devel@lists.01.org
  Cc: Tian, Feng, Zeng, Star, Kinney, Michael D, Gao, Liming,
	Zhang, Chao B, Wei, David

Reviewed-by: David Wei <david.wei@intel.com>

Thanks,
David  Wei                                 


-----Original Message-----
From: Yao, Jiewen 
Sent: Wednesday, September 21, 2016 2:45 PM
To: edk2-devel@lists.01.org
Cc: Wei, David <david.wei@intel.com>; Tian, Feng <feng.tian@intel.com>; Zeng, Star <star.zeng@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: [PATCH 43/45] Vlv2TbltDevicePkg/dsc/fdf: Add capsule/recovery support.

Add capsule and recovery support module in platform dsc and fdf.

Cc: David Wei <david.wei@intel.com>
Cc: Feng Tian <feng.tian@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Chao Zhang <chao.b.zhang@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
---
 Vlv2TbltDevicePkg/PlatformPkg.fdf       | 132 ++++++++++----------
 Vlv2TbltDevicePkg/PlatformPkgConfig.dsc |   3 +-
 Vlv2TbltDevicePkg/PlatformPkgGcc.fdf    | 132 ++++++++++----------
 Vlv2TbltDevicePkg/PlatformPkgGccX64.dsc |  70 ++++++++++-
 Vlv2TbltDevicePkg/PlatformPkgIA32.dsc   |  70 ++++++++++-
 Vlv2TbltDevicePkg/PlatformPkgX64.dsc    |  70 ++++++++++-
 6 files changed, 341 insertions(+), 136 deletions(-)

diff --git a/Vlv2TbltDevicePkg/PlatformPkg.fdf b/Vlv2TbltDevicePkg/PlatformPkg.fdf
index 93b4d2d..7a793bd 100644
--- a/Vlv2TbltDevicePkg/PlatformPkg.fdf
+++ b/Vlv2TbltDevicePkg/PlatformPkg.fdf
@@ -82,6 +82,9 @@ NumBlocks     = $(FLASH_NUM_BLOCKS)          #The number of blocks in 3Mb FLASH
 SET gPlatformModuleTokenSpaceGuid.PcdFlashAreaBaseAddress            = $(FLASH_AREA_BASE_ADDRESS)
 SET gPlatformModuleTokenSpaceGuid.PcdFlashAreaSize                   = $(FLASH_AREA_SIZE)
 
+SET gUefiCpuPkgTokenSpaceGuid.PcdCpuMicrocodePatchAddress = $(FLASH_REGION_VLVMICROCODE_BASE) + 0x60
+SET gUefiCpuPkgTokenSpaceGuid.PcdCpuMicrocodePatchRegionSize = $(FLASH_REGION_VLVMICROCODE_SIZE) - 0x60
+
 !if $(MINNOW2_FSP_BUILD) == TRUE
 # put below PCD value setting into dsc file
 #SET gFspWrapperTokenSpaceGuid.PcdCpuMicrocodePatchAddress                = $(FLASH_REGION_VLVMICROCODE_BASE)
@@ -242,6 +245,34 @@ FILE RAW = 197DB236-F856-4924-90F8-CDF12FB875F3 {
   $(OUTPUT_DIRECTORY)\$(TARGET)_$(TOOL_CHAIN_TAG)\$(DXE_ARCHITECTURE)\MicrocodeUpdates.bin
 }
 
+!if $(RECOVERY_ENABLE)
+[FV.FVRECOVERY_COMPONENTS]
+FvAlignment        = 16         #FV alignment and FV attributes setting.
+ERASE_POLARITY     = 1
+MEMORY_MAPPED      = TRUE
+STICKY_WRITE       = TRUE
+LOCK_CAP           = TRUE
+LOCK_STATUS        = TRUE
+WRITE_DISABLED_CAP = TRUE
+WRITE_ENABLED_CAP  = TRUE
+WRITE_STATUS       = TRUE
+WRITE_LOCK_CAP     = TRUE
+WRITE_LOCK_STATUS  = TRUE
+READ_DISABLED_CAP  = TRUE
+READ_ENABLED_CAP   = TRUE
+READ_STATUS        = TRUE
+READ_LOCK_CAP      = TRUE
+READ_LOCK_STATUS   = TRUE
+
+INF  RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/PchUsb.inf
+INF  MdeModulePkg/Bus/Pci/EhciPei/EhciPei.inf
+INF  MdeModulePkg/Bus/Usb/UsbBusPei/UsbBusPei.inf
+INF  MdeModulePkg/Bus/Usb/UsbBotPei/UsbBotPei.inf
+INF  FatPkg/FatPei/FatPei.inf
+INF  MdeModulePkg/Universal/Disk/CdExpressPei/CdExpressPei.inf
+INF  MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPei.inf
+!endif
+
 ################################################################################
 #
 # FV Section
@@ -306,6 +337,15 @@ INF MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf
 INF MdeModulePkg/Universal/ReportStatusCodeRouter/Pei/ReportStatusCodeRouterPei.inf
 !endif
 
+!if $(RECOVERY_ENABLE)
+FILE FV_IMAGE = 1E9D7604-EF45-46a0-BD8A-71AC78C17AC1 {
+  SECTION PEI_DEPEX_EXP = {gEfiPeiMemoryDiscoveredPpiGuid AND gEfiPeiBootInRecoveryModePpiGuid}
+  SECTION GUIDED EE4E5898-3914-4259-9D6E-DC7BD79403CF {    # LZMA COMPRESS GUID
+    SECTION FV_IMAGE = FVRECOVERY_COMPONENTS
+  }
+}
+!endif
+
 [FV.FVRECOVERY]
 BlockSize          = $(FLASH_BLOCK_SIZE)
 FvAlignment        = 16         #FV alignment and FV attributes setting.
@@ -373,6 +413,11 @@ INF RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET
 
 INF MdeModulePkg/Universal/PCD/Pei/Pcd.inf
 
+!if $(CAPSULE_ENABLE) || $(RECOVERY_ENABLE)
+  # FMP image decriptor
+INF RuleOverride = FMP_IMAGE_DESC Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptor.inf
+!endif
+
 [FV.FVMAIN]
 BlockSize          = $(FLASH_BLOCK_SIZE)
 FvAlignment        = 16
@@ -717,6 +762,12 @@ FILE FREEFORM = 878AC2CC-5343-46F2-B563-51F89DAF56BA {
   !endif
 !endif
 
+!if $(CAPSULE_ENABLE)
+INF  MdeModulePkg/Universal/EsrtDxe/EsrtDxe.inf
+INF  MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxe.inf
+INF  UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.inf
+!endif
+
 [FV.FVMAIN_COMPACT]
 BlockSize          = $(FLASH_BLOCK_SIZE)
 FvAlignment        = 16
@@ -780,8 +831,8 @@ READ_LOCK_CAP      = TRUE
 READ_LOCK_STATUS   = TRUE
 
 
-[FV.Update_Data]
-BlockSize          = $(FLASH_BLOCK_SIZE)
+!if $(CAPSULE_ENABLE) || $(RECOVERY_ENABLE)
+[FV.CapsuleDispatchFv]
 FvAlignment        = 16
 ERASE_POLARITY     = 1
 MEMORY_MAPPED      = TRUE
@@ -799,71 +850,11 @@ READ_STATUS        = TRUE
 READ_LOCK_CAP      = TRUE
 READ_LOCK_STATUS   = TRUE
 
-FILE RAW = 88888888-8888-8888-8888-888888888888 {
-       FD = Vlv
-     }
-
-[FV.BiosUpdateCargo]
-BlockSize          = $(FLASH_BLOCK_SIZE)
-FvAlignment        = 16
-ERASE_POLARITY     = 1
-MEMORY_MAPPED      = TRUE
-STICKY_WRITE       = TRUE
-LOCK_CAP           = TRUE
-LOCK_STATUS        = TRUE
-WRITE_DISABLED_CAP = TRUE
-WRITE_ENABLED_CAP  = TRUE
-WRITE_STATUS       = TRUE
-WRITE_LOCK_CAP     = TRUE
-WRITE_LOCK_STATUS  = TRUE
-READ_DISABLED_CAP  = TRUE
-READ_ENABLED_CAP   = TRUE
-READ_STATUS        = TRUE
-READ_LOCK_CAP      = TRUE
-READ_LOCK_STATUS   = TRUE
-
-
-
-[FV.BiosUpdate]
-BlockSize          = $(FLASH_BLOCK_SIZE)
-FvAlignment        = 16
-ERASE_POLARITY     = 1
-MEMORY_MAPPED      = TRUE
-STICKY_WRITE       = TRUE
-LOCK_CAP           = TRUE
-LOCK_STATUS        = TRUE
-WRITE_DISABLED_CAP = TRUE
-WRITE_ENABLED_CAP  = TRUE
-WRITE_STATUS       = TRUE
-WRITE_LOCK_CAP     = TRUE
-WRITE_LOCK_STATUS  = TRUE
-READ_DISABLED_CAP  = TRUE
-READ_ENABLED_CAP   = TRUE
-READ_STATUS        = TRUE
-READ_LOCK_CAP      = TRUE
-READ_LOCK_STATUS   = TRUE
-
-[Capsule.Capsule_Boot]
-#
-# gEfiCapsuleGuid supported by platform
-# { 0x3B6686BD, 0x0D76, 0x4030, { 0xB7, 0x0E, 0xB5, 0x51, 0x9E, 0x2F, 0xC5, 0xA0 }}
-#
-CAPSULE_GUID  = 3B6686BD-0D76-4030-B70E-B5519E2FC5A0
-CAPSULE_FLAGS = PersistAcrossReset
-CAPSULE_HEADER_SIZE = 0x20
-
-FV = BiosUpdate
-
-[Capsule.Capsule_Reset]
-#
-# gEfiCapsuleGuid supported by platform
-# { 0x3B6686BD, 0x0D76, 0x4030, { 0xB7, 0x0E, 0xB5, 0x51, 0x9E, 0x2F, 0xC5, 0xA0 }}
-#
-CAPSULE_GUID  = 3B6686BD-0D76-4030-B70E-B5519E2FC5A0
-CAPSULE_FLAGS = PersistAcrossReset
-CAPSULE_HEADER_SIZE = 0x20
+!if $(CAPSULE_ENABLE)
+INF  MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxe.inf
+!endif
 
-FV = BiosUpdate
+!endif
 
 ################################################################################
 #
@@ -1089,3 +1080,12 @@ FV = BiosUpdate
     RAW ASL   Optional            |.aml
   }
 
+[Rule.Common.PEIM.FMP_IMAGE_DESC]
+  FILE PEIM = $(NAMED_GUID) {
+     RAW BIN                  |.acpi
+     PEI_DEPEX PEI_DEPEX Optional        $(INF_OUTPUT)/$(MODULE_NAME).depex
+     PE32      PE32    Align=4K          $(INF_OUTPUT)/$(MODULE_NAME).efi
+     UI       STRING="$(MODULE_NAME)" Optional
+     VERSION  STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+  }
+
diff --git a/Vlv2TbltDevicePkg/PlatformPkgConfig.dsc b/Vlv2TbltDevicePkg/PlatformPkgConfig.dsc
index db50b93..a6af8a1 100644
--- a/Vlv2TbltDevicePkg/PlatformPkgConfig.dsc
+++ b/Vlv2TbltDevicePkg/PlatformPkgConfig.dsc
@@ -1,7 +1,7 @@
 #/** @file
 # platform configuration file.
 #
-# Copyright (c) 2012  - 2015, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2012  - 2016, Intel Corporation. All rights reserved.<BR>
 #                                                                                  

 # This program and the accompanying materials are licensed and made available under

 # the terms and conditions of the BSD License that accompanies this distribution.  

@@ -65,6 +65,7 @@ DEFINE VARIABLE_INFO_ENABLE = FALSE
 DEFINE S3_ENABLE = TRUE
 DEFINE CAPSULE_ENABLE = FALSE
 DEFINE CAPSULE_RESET_ENABLE = TRUE
+DEFINE RECOVERY_ENABLE = FALSE
 
 DEFINE GOP_DRIVER_ENABLE = TRUE
 DEFINE DATAHUB_ENABLE = TRUE
diff --git a/Vlv2TbltDevicePkg/PlatformPkgGcc.fdf b/Vlv2TbltDevicePkg/PlatformPkgGcc.fdf
index 33f2038..4dfc09d 100644
--- a/Vlv2TbltDevicePkg/PlatformPkgGcc.fdf
+++ b/Vlv2TbltDevicePkg/PlatformPkgGcc.fdf
@@ -82,6 +82,9 @@ NumBlocks     = $(FLASH_NUM_BLOCKS)          #The number of blocks in 3Mb FLASH
 SET gPlatformModuleTokenSpaceGuid.PcdFlashAreaBaseAddress            = $(FLASH_AREA_BASE_ADDRESS)
 SET gPlatformModuleTokenSpaceGuid.PcdFlashAreaSize                   = $(FLASH_AREA_SIZE)
 
+SET gUefiCpuPkgTokenSpaceGuid.PcdCpuMicrocodePatchAddress = $(FLASH_REGION_VLVMICROCODE_BASE) + 0x60
+SET gUefiCpuPkgTokenSpaceGuid.PcdCpuMicrocodePatchRegionSize = $(FLASH_REGION_VLVMICROCODE_SIZE) - 0x60
+
 !if $(MINNOW2_FSP_BUILD) == TRUE
 # put below PCD value setting into dsc file
 #SET gFspWrapperTokenSpaceGuid.PcdCpuMicrocodePatchAddress                = $(FLASH_REGION_VLVMICROCODE_BASE)
@@ -199,6 +202,34 @@ FILE RAW = 197DB236-F856-4924-90F8-CDF12FB875F3 {
   $(OUTPUT_DIRECTORY)/$(TARGET)_$(TOOL_CHAIN_TAG)/$(DXE_ARCHITECTURE)/MicrocodeUpdates.bin
 }
 
+!if $(RECOVERY_ENABLE) == TRUE
+[FV.FVRECOVERY_COMPONENTS]
+FvAlignment        = 16         #FV alignment and FV attributes setting.
+ERASE_POLARITY     = 1
+MEMORY_MAPPED      = TRUE
+STICKY_WRITE       = TRUE
+LOCK_CAP           = TRUE
+LOCK_STATUS        = TRUE
+WRITE_DISABLED_CAP = TRUE
+WRITE_ENABLED_CAP  = TRUE
+WRITE_STATUS       = TRUE
+WRITE_LOCK_CAP     = TRUE
+WRITE_LOCK_STATUS  = TRUE
+READ_DISABLED_CAP  = TRUE
+READ_ENABLED_CAP   = TRUE
+READ_STATUS        = TRUE
+READ_LOCK_CAP      = TRUE
+READ_LOCK_STATUS   = TRUE
+
+INF  RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/PchUsb.inf
+INF  MdeModulePkg/Bus/Pci/EhciPei/EhciPei.inf
+INF  MdeModulePkg/Bus/Usb/UsbBusPei/UsbBusPei.inf
+INF  MdeModulePkg/Bus/Usb/UsbBotPei/UsbBotPei.inf
+INF  FatPkg/FatPei/FatPei.inf
+INF  MdeModulePkg/Universal/Disk/CdExpressPei/CdExpressPei.inf
+INF  MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPei.inf
+!endif
+
 ################################################################################
 #
 # FV Section
@@ -263,6 +294,15 @@ INF MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf
 INF MdeModulePkg/Universal/ReportStatusCodeRouter/Pei/ReportStatusCodeRouterPei.inf
 !endif
 
+!if $(RECOVERY_ENABLE)
+FILE FV_IMAGE = 1E9D7604-EF45-46a0-BD8A-71AC78C17AC1 {
+  SECTION PEI_DEPEX_EXP = {gEfiPeiMemoryDiscoveredPpiGuid AND gEfiPeiBootInRecoveryModePpiGuid}
+  SECTION GUIDED EE4E5898-3914-4259-9D6E-DC7BD79403CF {    # LZMA COMPRESS GUID
+    SECTION FV_IMAGE = FVRECOVERY_COMPONENTS
+  }
+}
+!endif
+
 [FV.FVRECOVERY]
 BlockSize          = $(FLASH_BLOCK_SIZE)
 FvAlignment        = 16         #FV alignment and FV attributes setting.
@@ -330,6 +370,11 @@ INF RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET
 
 INF MdeModulePkg/Universal/PCD/Pei/Pcd.inf
 
+!if $(CAPSULE_ENABLE) || $(RECOVERY_ENABLE)
+  # FMP image decriptor
+INF RuleOverride = FMP_IMAGE_DESC Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptor.inf
+!endif
+
 [FV.FVMAIN]
 BlockSize          = $(FLASH_BLOCK_SIZE)
 FvAlignment        = 16
@@ -674,6 +719,12 @@ FILE FREEFORM = 878AC2CC-5343-46F2-B563-51F89DAF56BA {
   !endif
 !endif
 
+!if $(CAPSULE_ENABLE)
+INF  MdeModulePkg/Universal/EsrtDxe/EsrtDxe.inf
+INF  MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxe.inf
+INF  UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.inf
+!endif
+
 [FV.FVMAIN_COMPACT]
 BlockSize          = $(FLASH_BLOCK_SIZE)
 FvAlignment        = 16
@@ -737,8 +788,8 @@ READ_LOCK_CAP      = TRUE
 READ_LOCK_STATUS   = TRUE
 
 
-[FV.Update_Data]
-BlockSize          = $(FLASH_BLOCK_SIZE)
+!if $(CAPSULE_ENABLE) || $(RECOVERY_ENABLE)
+[FV.CapsuleDispatchFv]
 FvAlignment        = 16
 ERASE_POLARITY     = 1
 MEMORY_MAPPED      = TRUE
@@ -756,71 +807,11 @@ READ_STATUS        = TRUE
 READ_LOCK_CAP      = TRUE
 READ_LOCK_STATUS   = TRUE
 
-FILE RAW = 88888888-8888-8888-8888-888888888888 {
-       FD = Vlv
-     }
-
-[FV.BiosUpdateCargo]
-BlockSize          = $(FLASH_BLOCK_SIZE)
-FvAlignment        = 16
-ERASE_POLARITY     = 1
-MEMORY_MAPPED      = TRUE
-STICKY_WRITE       = TRUE
-LOCK_CAP           = TRUE
-LOCK_STATUS        = TRUE
-WRITE_DISABLED_CAP = TRUE
-WRITE_ENABLED_CAP  = TRUE
-WRITE_STATUS       = TRUE
-WRITE_LOCK_CAP     = TRUE
-WRITE_LOCK_STATUS  = TRUE
-READ_DISABLED_CAP  = TRUE
-READ_ENABLED_CAP   = TRUE
-READ_STATUS        = TRUE
-READ_LOCK_CAP      = TRUE
-READ_LOCK_STATUS   = TRUE
-
-
-
-[FV.BiosUpdate]
-BlockSize          = $(FLASH_BLOCK_SIZE)
-FvAlignment        = 16
-ERASE_POLARITY     = 1
-MEMORY_MAPPED      = TRUE
-STICKY_WRITE       = TRUE
-LOCK_CAP           = TRUE
-LOCK_STATUS        = TRUE
-WRITE_DISABLED_CAP = TRUE
-WRITE_ENABLED_CAP  = TRUE
-WRITE_STATUS       = TRUE
-WRITE_LOCK_CAP     = TRUE
-WRITE_LOCK_STATUS  = TRUE
-READ_DISABLED_CAP  = TRUE
-READ_ENABLED_CAP   = TRUE
-READ_STATUS        = TRUE
-READ_LOCK_CAP      = TRUE
-READ_LOCK_STATUS   = TRUE
-
-[Capsule.Capsule_Boot]
-#
-# gEfiCapsuleGuid supported by platform
-# { 0x3B6686BD, 0x0D76, 0x4030, { 0xB7, 0x0E, 0xB5, 0x51, 0x9E, 0x2F, 0xC5, 0xA0 }}
-#
-CAPSULE_GUID  = 3B6686BD-0D76-4030-B70E-B5519E2FC5A0
-CAPSULE_FLAGS = PersistAcrossReset
-CAPSULE_HEADER_SIZE = 0x20
-
-FV = BiosUpdate
-
-[Capsule.Capsule_Reset]
-#
-# gEfiCapsuleGuid supported by platform
-# { 0x3B6686BD, 0x0D76, 0x4030, { 0xB7, 0x0E, 0xB5, 0x51, 0x9E, 0x2F, 0xC5, 0xA0 }}
-#
-CAPSULE_GUID  = 3B6686BD-0D76-4030-B70E-B5519E2FC5A0
-CAPSULE_FLAGS = PersistAcrossReset
-CAPSULE_HEADER_SIZE = 0x20
+!if $(CAPSULE_ENABLE)
+INF  MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxe.inf
+!endif
 
-FV = BiosUpdate
+!endif
 
 ################################################################################
 #
@@ -1050,3 +1041,12 @@ FV = BiosUpdate
     RAW ASL   Optional            |.aml
   }
 
+[Rule.Common.PEIM.FMP_IMAGE_DESC]
+  FILE PEIM = $(NAMED_GUID) {
+     RAW BIN                  |.acpi
+     PEI_DEPEX PEI_DEPEX Optional        $(INF_OUTPUT)/$(MODULE_NAME).depex
+     PE32      PE32    Align=4K          $(INF_OUTPUT)/$(MODULE_NAME).efi
+     UI       STRING="$(MODULE_NAME)" Optional
+     VERSION  STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+  }
+
diff --git a/Vlv2TbltDevicePkg/PlatformPkgGccX64.dsc b/Vlv2TbltDevicePkg/PlatformPkgGccX64.dsc
index 7125366..47bb23e 100644
--- a/Vlv2TbltDevicePkg/PlatformPkgGccX64.dsc
+++ b/Vlv2TbltDevicePkg/PlatformPkgGccX64.dsc
@@ -183,10 +183,15 @@
 
   OemHookStatusCodeLib|MdeModulePkg/Library/OemHookStatusCodeLibNull/OemHookStatusCodeLibNull.inf
 !if $(CAPSULE_ENABLE) == TRUE
- CapsuleLib|IntelFrameworkModulePkg/Library/DxeCapsuleLib/DxeCapsuleLib.inf
+  CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.inf
 !else
   CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf
 !endif
+  EdkiiSystemCapsuleLib|MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.inf
+  FmpAuthenticationLib|MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.inf
+  IniParsingLib|MdeModulePkg/Library/IniParsingLib/IniParsingLib.inf
+  PlatformFlashAccessLib|Vlv2TbltDevicePkg/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.inf
+  MicrocodeFlashAccessLib|Vlv2TbltDevicePkg/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.inf
   LanguageLib|EdkCompatibilityPkg/Compatibility/Library/UefiLanguageLib/UefiLanguageLib.inf
   SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
   SecurityManagementLib|MdeModulePkg/Library/DxeSecurityManagementLib/DxeSecurityManagementLib.inf
@@ -381,6 +386,8 @@
   DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgentLib.inf
 !endif
 
+  FlashDeviceLib|$(PLATFORM_PACKAGE)/Library/FlashDeviceLib/FlashDeviceLibDxe.inf
+
 [LibraryClasses.X64.DXE_CORE]
   HobLib|MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.inf
   MemoryAllocationLib|MdeModulePkg/Library/DxeCoreMemoryAllocationLib/DxeCoreMemoryAllocationLib.inf
@@ -450,6 +457,10 @@
   DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgentLib.inf
 !endif
 
+!if $(CAPSULE_ENABLE)
+  CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf
+!endif
+
 [LibraryClasses.common.UEFI_DRIVER]
   PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
 
@@ -886,6 +897,11 @@
   gEfiVLVTokenSpaceGuid.PcdCpuSmramCpuDataAddress|0
   gEfiVLVTokenSpaceGuid.PcdCpuLockBoxSize|0
 
+!if $(CAPSULE_ENABLE) || $(RECOVERY_ENABLE)
+  gEfiMdeModulePkgTokenSpaceGuid.PcdEdkiiSystemFmpCapsuleImageTypeIdGuid|{0x7b, 0x26, 0x96, 0x40, 0x0a, 0xda, 0xeb, 0x42, 0xb5, 0xeb, 0xfe, 0xf3, 0x1d, 0x20, 0x7c, 0xb4}
+  gEfiMdeModulePkgTokenSpaceGuid.PcdEdkiiSystemFirmwareImageDescriptor|{0x0}|VOID*|0x100
+!endif
+
 [Components.IA32]
 
   $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/SecCore.inf
@@ -907,6 +923,14 @@
   }
   !endif
 
+!if $(CAPSULE_ENABLE) || $(RECOVERY_ENABLE)
+  # FMP image decriptor
+  Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptor.inf {
+    <LibraryClasses>
+      PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf
+  }
+!endif
+
   MdeModulePkg/Core/Pei/PeiMain.inf {
 !if $(TARGET) == DEBUG
     <PcdsFixedAtBuild>
@@ -1011,6 +1035,24 @@ $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/fTPMInitPeim.inf
   $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/MpS3.inf
   EdkCompatibilityPkg/Compatibility/AcpiVariableHobOnSmramReserveHobThunk/AcpiVariableHobOnSmramReserveHobThunk.inf
   $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/PiSmmCommunicationPei.inf
+
+!if $(RECOVERY_ENABLE)
+  #
+  # Recovery
+  #
+  $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/PchUsb.inf
+  MdeModulePkg/Bus/Pci/EhciPei/EhciPei.inf
+  MdeModulePkg/Bus/Usb/UsbBusPei/UsbBusPei.inf
+  MdeModulePkg/Bus/Usb/UsbBotPei/UsbBotPei.inf
+  FatPkg/FatPei/FatPei.inf
+  MdeModulePkg/Universal/Disk/CdExpressPei/CdExpressPei.inf
+  MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPei.inf {
+    <LibraryClasses>
+      NULL|SecurityPkg/Library/FmpAuthenticationRsa2048Sha256Lib/FmpAuthenticationRsa2048Sha256Lib.inf
+      PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf
+  }
+!endif
+
 !if $(CAPSULE_ENABLE) == TRUE
   MdeModulePkg/Universal/CapsulePei/CapsulePei.inf
 !endif
@@ -1146,6 +1188,9 @@ $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/fTPMInitPeim.inf
       DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
       PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
       SerialPortLib|$(PLATFORM_PACKAGE)/Library/SerialPortLib/SerialPortLib.inf
+!if $(CAPSULE_ENABLE) == TRUE
+      NULL|SecurityPkg/Library/FmpAuthenticationPkcs7Lib/FmpAuthenticationPkcs7Lib.inf
+!endif
     !if $(FTPM_ENABLE) == TRUE
       Tpm2DeviceLib|Vlv2TbltDevicePkg/Library/Tpm2DeviceLibSeCDxe/Tpm2DeviceLibSeC.inf
     !else
@@ -1518,6 +1563,29 @@ $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/fTPMInitPeim.inf
 
   Vlv2TbltDevicePkg/Application/FirmwareUpdate/FirmwareUpdate.inf
 
+!if $(CAPSULE_ENABLE)
+  MdeModulePkg/Universal/EsrtDxe/EsrtDxe.inf
+
+  MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxe.inf
+  MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxe.inf {
+    <LibraryClasses>
+      DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
+      PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
+      SerialPortLib|$(PLATFORM_PACKAGE)/Library/SerialPortLib/SerialPortLib.inf
+      NULL|SecurityPkg/Library/FmpAuthenticationPkcs7Lib/FmpAuthenticationPkcs7Lib.inf
+  }
+  MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf
+
+  UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.inf {
+    <LibraryClasses>
+      DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
+      PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
+      SerialPortLib|$(PLATFORM_PACKAGE)/Library/SerialPortLib/SerialPortLib.inf
+  }
+  UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.inf
+
+!endif
+
 [BuildOptions]
 #
 # Define Build Options both for EDK and EDKII drivers.
diff --git a/Vlv2TbltDevicePkg/PlatformPkgIA32.dsc b/Vlv2TbltDevicePkg/PlatformPkgIA32.dsc
index 6efaf32..5f46793 100644
--- a/Vlv2TbltDevicePkg/PlatformPkgIA32.dsc
+++ b/Vlv2TbltDevicePkg/PlatformPkgIA32.dsc
@@ -183,10 +183,15 @@
 
   OemHookStatusCodeLib|MdeModulePkg/Library/OemHookStatusCodeLibNull/OemHookStatusCodeLibNull.inf
 !if $(CAPSULE_ENABLE) == TRUE
- CapsuleLib|IntelFrameworkModulePkg/Library/DxeCapsuleLib/DxeCapsuleLib.inf
+  CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.inf
 !else
   CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf
 !endif
+  EdkiiSystemCapsuleLib|MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.inf
+  FmpAuthenticationLib|MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.inf
+  IniParsingLib|MdeModulePkg/Library/IniParsingLib/IniParsingLib.inf
+  PlatformFlashAccessLib|Vlv2TbltDevicePkg/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.inf
+  MicrocodeFlashAccessLib|Vlv2TbltDevicePkg/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.inf
   LanguageLib|EdkCompatibilityPkg/Compatibility/Library/UefiLanguageLib/UefiLanguageLib.inf
   SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
   SecurityManagementLib|MdeModulePkg/Library/DxeSecurityManagementLib/DxeSecurityManagementLib.inf
@@ -381,6 +386,8 @@
   DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgentLib.inf
 !endif
 
+  FlashDeviceLib|$(PLATFORM_PACKAGE)/Library/FlashDeviceLib/FlashDeviceLibDxe.inf
+
 [LibraryClasses.IA32.DXE_CORE]
   HobLib|MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.inf
   MemoryAllocationLib|MdeModulePkg/Library/DxeCoreMemoryAllocationLib/DxeCoreMemoryAllocationLib.inf
@@ -450,6 +457,10 @@
   DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgentLib.inf
 !endif
 
+!if $(CAPSULE_ENABLE) == TRUE
+  CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf
+!endif
+
 [LibraryClasses.common.UEFI_DRIVER]
   PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
 
@@ -888,6 +899,11 @@
   gEfiVLVTokenSpaceGuid.PcdCpuSmramCpuDataAddress|0
   gEfiVLVTokenSpaceGuid.PcdCpuLockBoxSize|0
 
+!if $(CAPSULE_ENABLE) || $(RECOVERY_ENABLE)
+  gEfiMdeModulePkgTokenSpaceGuid.PcdEdkiiSystemFmpCapsuleImageTypeIdGuid|{0x7b, 0x26, 0x96, 0x40, 0x0a, 0xda, 0xeb, 0x42, 0xb5, 0xeb, 0xfe, 0xf3, 0x1d, 0x20, 0x7c, 0xb4}
+  gEfiMdeModulePkgTokenSpaceGuid.PcdEdkiiSystemFirmwareImageDescriptor|{0x0}|VOID*|0x100
+!endif
+
 [Components.IA32]
 
   $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/SecCore.inf
@@ -909,6 +925,14 @@
   }
   !endif
 
+!if $(CAPSULE_ENABLE) || $(RECOVERY_ENABLE)
+  # FMP image decriptor
+  Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptor.inf {
+    <LibraryClasses>
+      PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf
+  }
+!endif
+
   MdeModulePkg/Core/Pei/PeiMain.inf {
 !if $(TARGET) == DEBUG
     <PcdsFixedAtBuild>
@@ -1008,6 +1032,24 @@ $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/fTPMInitPeim.inf
   $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/MpS3.inf
   EdkCompatibilityPkg/Compatibility/AcpiVariableHobOnSmramReserveHobThunk/AcpiVariableHobOnSmramReserveHobThunk.inf
   $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/PiSmmCommunicationPei.inf
+
+!if $(RECOVERY_ENABLE)
+  #
+  # Recovery
+  #
+  $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/PchUsb.inf
+  MdeModulePkg/Bus/Pci/EhciPei/EhciPei.inf
+  MdeModulePkg/Bus/Usb/UsbBusPei/UsbBusPei.inf
+  MdeModulePkg/Bus/Usb/UsbBotPei/UsbBotPei.inf
+  FatPkg/FatPei/FatPei.inf
+  MdeModulePkg/Universal/Disk/CdExpressPei/CdExpressPei.inf
+  MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPei.inf {
+    <LibraryClasses>
+      NULL|SecurityPkg/Library/FmpAuthenticationRsa2048Sha256Lib/FmpAuthenticationRsa2048Sha256Lib.inf
+      PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf
+  }
+!endif
+
 !if $(CAPSULE_ENABLE) == TRUE
   MdeModulePkg/Universal/CapsulePei/CapsulePei.inf
 !endif
@@ -1133,6 +1175,9 @@ $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/fTPMInitPeim.inf
       DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
       PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
       SerialPortLib|$(PLATFORM_PACKAGE)/Library/SerialPortLib/SerialPortLib.inf
+!if $(CAPSULE_ENABLE)
+      NULL|SecurityPkg/Library/FmpAuthenticationPkcs7Lib/FmpAuthenticationPkcs7Lib.inf
+!endif
     !if $(FTPM_ENABLE) == TRUE
       Tpm2DeviceLib|Vlv2TbltDevicePkg/Library/Tpm2DeviceLibSeCDxe/Tpm2DeviceLibSeC.inf
     !else
@@ -1499,6 +1544,29 @@ $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/fTPMInitPeim.inf
 
   Vlv2TbltDevicePkg/Application/FirmwareUpdate/FirmwareUpdate.inf
 
+!if $(CAPSULE_ENABLE)
+  MdeModulePkg/Universal/EsrtDxe/EsrtDxe.inf
+
+  MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxe.inf
+  MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxe.inf {
+    <LibraryClasses>
+      DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
+      PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
+      SerialPortLib|$(PLATFORM_PACKAGE)/Library/SerialPortLib/SerialPortLib.inf
+      NULL|SecurityPkg/Library/FmpAuthenticationPkcs7Lib/FmpAuthenticationPkcs7Lib.inf
+  }
+  MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf
+
+  UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.inf {
+    <LibraryClasses>
+      DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
+      PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
+      SerialPortLib|$(PLATFORM_PACKAGE)/Library/SerialPortLib/SerialPortLib.inf
+  }
+  UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.inf
+
+!endif
+
 [BuildOptions]
 #
 # Define Build Options both for EDK and EDKII drivers.
diff --git a/Vlv2TbltDevicePkg/PlatformPkgX64.dsc b/Vlv2TbltDevicePkg/PlatformPkgX64.dsc
index 6bb503d..b2ac048 100644
--- a/Vlv2TbltDevicePkg/PlatformPkgX64.dsc
+++ b/Vlv2TbltDevicePkg/PlatformPkgX64.dsc
@@ -183,10 +183,15 @@
 
   OemHookStatusCodeLib|MdeModulePkg/Library/OemHookStatusCodeLibNull/OemHookStatusCodeLibNull.inf
 !if $(CAPSULE_ENABLE) == TRUE
- CapsuleLib|IntelFrameworkModulePkg/Library/DxeCapsuleLib/DxeCapsuleLib.inf
+  CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.inf
 !else
   CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf
 !endif
+  EdkiiSystemCapsuleLib|MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.inf
+  FmpAuthenticationLib|MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.inf
+  IniParsingLib|MdeModulePkg/Library/IniParsingLib/IniParsingLib.inf
+  PlatformFlashAccessLib|Vlv2TbltDevicePkg/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.inf
+  MicrocodeFlashAccessLib|Vlv2TbltDevicePkg/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.inf
   LanguageLib|EdkCompatibilityPkg/Compatibility/Library/UefiLanguageLib/UefiLanguageLib.inf
   SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
   SecurityManagementLib|MdeModulePkg/Library/DxeSecurityManagementLib/DxeSecurityManagementLib.inf
@@ -381,6 +386,8 @@
   DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgentLib.inf
 !endif
 
+  FlashDeviceLib|$(PLATFORM_PACKAGE)/Library/FlashDeviceLib/FlashDeviceLibDxe.inf
+
 [LibraryClasses.X64.DXE_CORE]
   HobLib|MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.inf
   MemoryAllocationLib|MdeModulePkg/Library/DxeCoreMemoryAllocationLib/DxeCoreMemoryAllocationLib.inf
@@ -450,6 +457,10 @@
   DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgentLib.inf
 !endif
 
+!if $(CAPSULE_ENABLE)
+  CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf
+!endif
+
 [LibraryClasses.common.UEFI_DRIVER]
   PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
 
@@ -885,6 +896,11 @@
   gEfiVLVTokenSpaceGuid.PcdCpuSmramCpuDataAddress|0
   gEfiVLVTokenSpaceGuid.PcdCpuLockBoxSize|0
 
+!if $(CAPSULE_ENABLE) || $(RECOVERY_ENABLE)
+  gEfiMdeModulePkgTokenSpaceGuid.PcdEdkiiSystemFmpCapsuleImageTypeIdGuid|{0x7b, 0x26, 0x96, 0x40, 0x0a, 0xda, 0xeb, 0x42, 0xb5, 0xeb, 0xfe, 0xf3, 0x1d, 0x20, 0x7c, 0xb4}
+  gEfiMdeModulePkgTokenSpaceGuid.PcdEdkiiSystemFirmwareImageDescriptor|{0x0}|VOID*|0x100
+!endif
+
 [Components.IA32]
 
   $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/SecCore.inf
@@ -906,6 +922,14 @@
   }
   !endif
 
+!if $(CAPSULE_ENABLE) || $(RECOVERY_ENABLE)
+  # FMP image decriptor
+  Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptor.inf {
+    <LibraryClasses>
+      PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf
+  }
+!endif
+
   MdeModulePkg/Core/Pei/PeiMain.inf {
 !if $(TARGET) == DEBUG
     <PcdsFixedAtBuild>
@@ -1005,6 +1029,24 @@ $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/fTPMInitPeim.inf
   $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/MpS3.inf
   EdkCompatibilityPkg/Compatibility/AcpiVariableHobOnSmramReserveHobThunk/AcpiVariableHobOnSmramReserveHobThunk.inf
   $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/PiSmmCommunicationPei.inf
+
+!if $(RECOVERY_ENABLE)
+  #
+  # Recovery
+  #
+  $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/PchUsb.inf
+  MdeModulePkg/Bus/Pci/EhciPei/EhciPei.inf
+  MdeModulePkg/Bus/Usb/UsbBusPei/UsbBusPei.inf
+  MdeModulePkg/Bus/Usb/UsbBotPei/UsbBotPei.inf
+  FatPkg/FatPei/FatPei.inf
+  MdeModulePkg/Universal/Disk/CdExpressPei/CdExpressPei.inf
+  MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPei.inf {
+    <LibraryClasses>
+      NULL|SecurityPkg/Library/FmpAuthenticationRsa2048Sha256Lib/FmpAuthenticationRsa2048Sha256Lib.inf
+      PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf
+  }
+!endif
+
 !if $(CAPSULE_ENABLE) == TRUE
   MdeModulePkg/Universal/CapsulePei/CapsulePei.inf
 !endif
@@ -1139,6 +1181,9 @@ $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/fTPMInitPeim.inf
       DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
       PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
       SerialPortLib|$(PLATFORM_PACKAGE)/Library/SerialPortLib/SerialPortLib.inf
+!if $(CAPSULE_ENABLE)
+      NULL|SecurityPkg/Library/FmpAuthenticationPkcs7Lib/FmpAuthenticationPkcs7Lib.inf
+!endif
     !if $(FTPM_ENABLE) == TRUE
       Tpm2DeviceLib|Vlv2TbltDevicePkg/Library/Tpm2DeviceLibSeCDxe/Tpm2DeviceLibSeC.inf
     !else
@@ -1505,6 +1550,29 @@ $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/fTPMInitPeim.inf
 
   Vlv2TbltDevicePkg/Application/FirmwareUpdate/FirmwareUpdate.inf
 
+!if $(CAPSULE_ENABLE)
+  MdeModulePkg/Universal/EsrtDxe/EsrtDxe.inf
+
+  MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxe.inf
+  MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxe.inf {
+    <LibraryClasses>
+      DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
+      PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
+      SerialPortLib|$(PLATFORM_PACKAGE)/Library/SerialPortLib/SerialPortLib.inf
+      NULL|SecurityPkg/Library/FmpAuthenticationPkcs7Lib/FmpAuthenticationPkcs7Lib.inf
+  }
+  MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf
+
+  UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.inf {
+    <LibraryClasses>
+      DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
+      PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
+      SerialPortLib|$(PLATFORM_PACKAGE)/Library/SerialPortLib/SerialPortLib.inf
+  }
+  UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.inf
+
+!endif
+
 [BuildOptions]
 #
 # Define Build Options both for EDK and EDKII drivers.
-- 
2.7.4.windows.1



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

* Re: [PATCH 00/45] Add capsule update and recovery sample.
  2016-09-21 16:35 ` [PATCH 00/45] Add capsule update and recovery sample Kinney, Michael D
@ 2016-09-22  1:59   ` Yao, Jiewen
  0 siblings, 0 replies; 83+ messages in thread
From: Yao, Jiewen @ 2016-09-22  1:59 UTC (permalink / raw)
  To: Kinney, Michael D, edk2-devel@lists.01.org
  Cc: Tian, Feng, Gao, Liming, Zeng, Star, Fan, Jeff, Zhang, Chao B

Thanks, Mike. That is very good suggestion. See below detail:

For feature testing, I did below:

1)      CapsuleUpdate

a)       Test capsule with EDKII System Capsule PKCS7 format.

b)       Capsule Generation: in build phase.

c)        Capsule trigger: In UEFI SHELL, use CapsuleApp in this patch.

d)       Platform: an internal Platform, MinnowMax and Quark.

e)       No auth header, or auth fail: rejected.

f)        Version lower: rejected.

2)      Recovery

a)       Test capsule with EDKII System Capsule RSA2048SHA256 format.

b)       Capsule Generation: in build phase.

c)        Recovery Media: USB KEY.

d)       Platform: an internal platform, MinnowMax. (Quark platform has USB issue in PEI phase and cause system resest. So I cannot test Quark)

e)       No auth header, or auth fail: rejected.

f)        Version mismatch: rejected.

3)      MicrocodeUpdate

a)       Test capsule with Microcode FMP format.

b)       Capsule Generation: in UEFI SHELL use MicrocodeCapsuleApp, or in build phase.

c)        Capsule trigger: In UEFI SHELL, use CapsuleApp in this patch.

d)       Platform: an internal Platform, MinnowMax. (Not for Quark, because Quark uses different style binary)

e)       ProcessorSignature/ProcessorFlags mismatch: rejected.

f)        MicrocodeLoad fail: rejected.

The API which will get direct external input is below:

1)  MdeModulePkg\Library\DxeCapsuleLibFmp\DxeCapsuleLib.c:

a)   SupportCapsuleImage()

b)   ProcessCapsuleImage()

c)   IsValidCapsuleHeader()

d)   ValidateFmpCapsule() <== This is the API to valid the FMP capsule header.

e)   DisplayCapsuleImage() <== This is the API to process UX capsule.

f)   ConvertBmpToGopBlt() <== This is the API to parse BMP

2)  MdeModulePkg\Library\DxeCapsuleLibFmp\DxeCapsuleProcessLib.c:

a)   ProcessTheseCapsules()

3)  MdeModulePkg\Library\EdkiiSystemCapsuleLib\EdkiiSystemCapsuleLib.c

a)   CapsuleAuthenticateSystemFirmware()

4)  MdeModulePkg\Library\FmpAuthenitcationLib\FmpAuthenitcationLib.c

a)   ExecuteFmpAuthenticationHandler() <== This is the API to valid FMP AUTH HEADER.

5)  MdeModulePkg\Universal\SystemBiosUpdate\SystemBiosMainSetImage.c

a)   BiosAuthenticatedUpdate()

6)  MdeModulePkg\Universal\RecoveryModuleLoadPei\RecoveryModuleLoadPei.c

a)   ProcessRecoveryCapsule()

b)   ProcessFmpCapsuleImage ()

c)   ProcessRecoveryImage ()

d)   IsValidCapsuleHeader()

e)   ValidateFmpCapsule () <== This is the API to valid the FMP capsule header.

7)  SecurityPkg\Library\FmpAuthenticationPkcs7Lib\FmpAuthenticationPkcs7Lib.c

a)   FmpAuthenticatedHandlerPkcs7() <== This is the API to valid FMP PKCS7 AUTH data

8)  SecurityPkg\Library\FmpAuthenticationRsa2048Sha256Lib\FmpAuthenticationRsa2048Sha256Lib.c

a)   FmpAuthenticatedHandlerRsa2048Sha256 () <== This is the API to valid FMP RSA2048SHA256 AUTH data

9)  UefiCpuPkg\MicrocodeUpdate\MicrocodeUpdate.c

a)   VerifyMicrocode () <== This is the API to valid Microcode capsule.
The RED part is the goal keeper.

For security testing, I did below:
The capsule image is external input, so those API need validate the format.

1)      FMP capsule

a)       Unit Test: Generate invalid field below:

        i.     EFI_CAPSULE_HEADER.CapsuleGuid (All zero)

       ii.     EFI_CAPSULE_HEADER.HeaderSize (0)

     iii.     EFI_CAPSULE_HEADER.CapsuleImageSize (0, 0xFFFFFFFF)

       iv.     EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER.Version (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION - 1, EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION + 1)

        v.     EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER.EmbeddedDriverCount (0, 0xFFFF)

       vi.     EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER.PayloadItemCount (0, 0xFFFF)

     vii.     EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER.ItemOffsetList (0, 0xFFFFFFFF, 0xFFFFFFFFFFFFFFFF)

    viii.     EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER.Version (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION - 1, EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION + 1)

       ix.     EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER.UpdateImageSize (0, 0xFFFFFFFF, Valid - 1)

        x.     EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER.UpdateVendorCodeSize (0xFFFFFFFF)

       xi.     EFI_FIRMWARE_IMAGE_AUTHENTICATION.UpdateImageTypeId (all zero)

     xii.     EFI_FIRMWARE_IMAGE_AUTHENTICATION.AuthInfo.Hdr.dwLength (0, 0xFFFFFFFF)

    xiii.     EFI_FIRMWARE_IMAGE_AUTHENTICATION.AuthInfo.Hdr.wRevision (Valid  - 1, Valid + 1)

     xiv.     EFI_FIRMWARE_IMAGE_AUTHENTICATION.AuthInfo.Hdr.wCertificateType (0)

       xv.     EFI_FIRMWARE_IMAGE_AUTHENTICATION.AuthInfo.CertType (all zero)

b)       Fuzzing Test: Generate invalid field below: (Similar to above)

        i.     EFI_CAPSULE_HEADER

       ii.     EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER

     iii.     EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER

       iv.     EFI_FIRMWARE_IMAGE_AUTHENTICATION

2)      Microsoft defined UX capsule

a)       Unit Test: Generate invalid field below:

        i.     EFI_CAPSULE_HEADER.CapsuleGuid (All zero)

       ii.     EFI_CAPSULE_HEADER.HeaderSize (0)

     iii.     EFI_CAPSULE_HEADER.CapsuleImageSize (0, 0xFFFFFFFF)

       iv.     EFI_DISPLAY_CAPSULE.ImagePayload.Version (Valid - 1, Valid + 1)

        v.     EFI_DISPLAY_CAPSULE.ImagePayload.Checksum (~Valid)

       vi.     EFI_DISPLAY_CAPSULE.ImagePayload.ImageType (Valid - 1, Valid + 1)

     vii.     EFI_DISPLAY_CAPSULE.ImagePayload.Mode (Valid - 1, Valid + 1)

    viii.     EFI_DISPLAY_CAPSULE.ImagePayload.OffsetX (0xFFFFFFFF, Gop->Mode->Info->HorizontalResolution)

       ix.     EFI_DISPLAY_CAPSULE.ImagePayload.OffsetY (0xFFFFFFFF, Gop->Mode->Info->VerticalResolution)

b)       Fuzzing Test: Generate invalid field below: (Similar to above)

        i.     EFI_CAPSULE_HEADER

       ii.     EFI_DISPLAY_CAPSULE.ImagePayload

3)      Microcode capsule

a)       Unit Test: Generate invalid field below:

        i.     CPU_MICROCODE_HEADER.HeaderVersion (0)

       ii.     CPU_MICROCODE_HEADER.UpdateVersion (0)

     iii.     CPU_MICROCODE_HEADER.ProcessorSignature.Uint32 (0)

       iv.     CPU_MICROCODE_HEADER.Checksum (~Valid)

        v.     CPU_MICROCODE_HEADER.LoaderRevision (0)

       vi.     CPU_MICROCODE_HEADER.ProcessorFlags (0)

     vii.     CPU_MICROCODE_HEADER.DataSize (1, 0xFFFFFFFF)

    viii.     CPU_MICROCODE_HEADER.TotalSize (1, 0xFFFFFFFF)

       ix.     CPU_MICROCODE_EXTENDED_TABLE_HEADER.ExtendedSignatureCount (0, 0xFFFFFFFF)

        x.     CPU_MICROCODE_EXTENDED_TABLE_HEADER.Checksum (~Valid)

       xi.     CPU_MICROCODE_EXTENDED_TABLE_HEADER.ProcessorSignature.Uint32 (0)

     xii.     CPU_MICROCODE_EXTENDED_TABLE_HEADER.ProcessorFlags (0)

    xiii.     CPU_MICROCODE_EXTENDED_TABLE.Checksum (~Valid)

b)       Fuzzing Test: Generate invalid field below: (Similar to above)

        i.     CPU_MICROCODE_HEADER

If reviewed can help double check the API and test case, to see if the validation is enough, that will be great.
I will be happy to add more test per request.

Thank you
Yao Jiewen

From: Kinney, Michael D
Sent: Thursday, September 22, 2016 12:36 AM
To: Yao, Jiewen <jiewen.yao@intel.com>; edk2-devel@lists.01.org; Kinney, Michael D <michael.d.kinney@intel.com>
Cc: Tian, Feng <feng.tian@intel.com>; Gao, Liming <liming.gao@intel.com>; Zeng, Star <star.zeng@intel.com>; Fan, Jeff <jeff.fan@intel.com>; Zhang, Chao B <chao.b.zhang@intel.com>
Subject: RE: [edk2] [PATCH 00/45] Add capsule update and recovery sample.

Jiewen,

Thanks for this contribution and thank you for also providing a version of
it on your GitHub fork to make it easier for some to evaluate such a large
series.

Can you provide a more detailed summary of this feature along with
A summary of any testing that has already been performed?


I see some of the comments have a Caution about an API taking external
input.  This implies that some amount of security analysis and review
may have already been performed.  The summary should include the set of
APIs that do take external input and what review or testing was done on
those APIs?

What amount of additional testing do you think this series requires?

Thanks,

Mike

> -----Original Message-----
> From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of Jiewen Yao
> Sent: Tuesday, September 20, 2016 11:45 PM
> To: edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>
> Cc: Tian, Feng <feng.tian@intel.com<mailto:feng.tian@intel.com>>; Gao, Liming <liming.gao@intel.com<mailto:liming.gao@intel.com>>; Zeng, Star
> <star.zeng@intel.com<mailto:star.zeng@intel.com>>; Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>; Fan, Jeff
> <jeff.fan@intel.com<mailto:jeff.fan@intel.com>>; Zhang, Chao B <chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com>>
> Subject: [edk2] [PATCH 00/45] Add capsule update and recovery sample.
>
> This series patch provides sample on how to do signed capsule update
> and recovery in EDKII.
>
> This series patch is also checked into git@github.com:jyao1/edk2.git<mailto:git@github.com:jyao1/edk2.git>.
>
> The feature includes:
> 1) Define EDKII signed system BIOS capsule format.
> 2) Provide EDKII signed system BIOS update sample.
> 3) Provide EDKII signed recovery sample.
> 4) Provide Microcode update sample for X86 system.
> 5) Update Quark to use new capsule/recovery solution.
> 6) Update Vlv2(MinnowMax) to use new capsule/recovery solution.
>
> The signed capsule/recovery solution is in MdeModulePkg.
> The capsule in IntelFrameworkModulePkg is deprecated.
> The Microcode update solution is in UefiCpuPkg.
>
> Cc: Feng Tian <feng.tian@intel.com<mailto:feng.tian@intel.com>>
> Cc: Star Zeng <star.zeng@intel.com<mailto:star.zeng@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 Zhang <chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com>>
> Cc: Jeff Fan <jeff.fan@intel.com<mailto:jeff.fan@intel.com>>
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Jiewen Yao <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>
>
>
> Jiewen Yao (45):
>   MdeModulePkg/Include: Add EDKII system FMP capsule header.
>   MdeModulePkg/Include: Add EdkiiSystemCapsuleLib definition.
>   MdeModulePkg/Include: Add FmpAuthenticationLib header.
>   MdeModulePkg/Include: Add IniParsingLib header.
>   MdeModulePkg/Include: Add PlatformFlashAccessLib header.
>   MdeModulePkg/CapsuleLib: Add ProcessCapsules() API.
>   MdeModulePkg/MdeModulePkg.dec: Add capsule related definition.
>   MdeModulePkg/IniParsingLib: Add InitParsingLib instance.
>   MdeModulePkg/FmpAuthenticationLib: Add FmpAuthenticationLib instance.
>   MdeModulePkg/DxeCapsuleLibFmp: Add DxeCapsuleLibFmp instance.
>   MdeModulePkg/DxeCapsuleLibNull: Add ProcessCapsules() interface.
>   MdeModulePkg/EdkiiSystemCapsuleLib: Add EdkiiSystemCapsuleLib
>     instance.
>   MdeModulePkg/PlatformFlashAccessLib: Add NULL PlatformFlashAccessLib.
>   MdeModulePkg/Esrt: Add ESRT_FW_TYPE_SYSTEMFIRMWARE check.
>   MdeModulePkg/SystemBiosUpdate: Add SystemBiosUpdate component.
>   MdeModulePkg/RecoveryModuleLoadPei: Add RecoveryModuleLoadPei.
>   MdeModulePkg/CapsuleApp: Add CapsuleApp application.
>   MdeModulePkg/MdeModulePkg.dsc: Add capsule related component.
>   IntelFrameworkModulePkg/DxeCapsuleLib: Add ProcessCapsules()
>     interface.
>   SecurityPkg/SecurityPkg.dec: Add PcdPkcs7CertBuffer PCD.
>   SecurityPkg/FmpAuthenticationPkcs7Lib: Add PKCS7 NULL class for FMP.
>   SecurityPkg/FmpAuthenticationRsa2048Sha256Lib: Add NULL class for FMP.
>   SecurityPkg/SecurityPkg.dsc: Add FmpAuthentication*Lib.
>   UefiCpuPkg/Include: Add Microcode FMP definition.
>   UefiCpuPkg/Include: Add MicrocodeFlashAccessLib header.
>   UefiCpuPkg/UefiCpuPkg.dec: Add Microcode capsule related definition.
>   UefiCpuPkg/MicrocodeUpdate: Add MicrocodeUpdate component.
>   UefiCpuPkg/MicrocodeFlashAccessLib: Add NULL MicrocodeFlashAccessLib.
>   UefiCpuPkg/MicrocodeCapsuleApp: Add MicrocodeCapsuleApp application.
>   UefiCpuPkg/UefiCpuPkg.dsc: Add MicrocodeCapsule related component.
>   QuarkPlatformPkg/PlatformFlashAccessLib: Add instance for capsule
>     update.
>   QuarkPlatformPkg/SystemBiosDescriptor: Add Descriptor for capsule
>     update.
>   QuarkPlatformPkg/SystemBiosUpdateConfig: Add capsule config file.
>   QuarkPlatformPkg/PlatformInit: Remove recovery PPI installation.
>   QuarkPlatformPkg/PlatformBootManager: Add capsule/recovery handling.
>   QuarkPlatformPkg/dsc/fdf: Add capsule/recovery support.
>   QuarkPlatformPkg/dsc/fdf: add capsule generation DSC/FDF.
>   Vlv2TbltDevicePkg/PlatformFlashAccessLib: Add instance for capsule
>     update.
>   Vlv2TbltDevicePkg/SystemBiosDescriptor: Add Descriptor for capsule
>     update.
>   Vlv2TbltDevicePkg/SystemBiosUpdateConfig: Add capsule config file.
>   Vlv2TbltDevicePkg/FlashDeviceLib: Add DXE flash device lib.
>   Vlv2TbltDevicePkg/PlatformBootManager: Add capsule/recovery handling.
>   Vlv2TbltDevicePkg/dsc/fdf: Add capsule/recovery support.
>   Vlv2TbltDevicePkg/dsc/fdf: add capsule generation DSC/FDF.
>   Vlv2TbltDevicePkg/bat: add capsule generation in bat.
>
>  IntelFrameworkModulePkg/Library/DxeCapsuleLib/DxeCapsuleLib.c
> |   39 +-
>  MdeModulePkg/Application/CapsuleApp/AppSupport.c
> |  480 ++++++
>  MdeModulePkg/Application/CapsuleApp/CapsuleApp.c
> | 1047 +++++++++++++
>  MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf
> |   71 +
>  MdeModulePkg/Application/CapsuleApp/CapsuleApp.uni
> |   22 +
>  MdeModulePkg/Application/CapsuleApp/CapsuleAppExtra.uni
> |   19 +
>  MdeModulePkg/Application/CapsuleApp/CapsuleDump.c
> |  840 +++++++++++
>  MdeModulePkg/Include/Guid/EdkiiSystemFmpCapsule.h
> |  110 ++
>  MdeModulePkg/Include/Library/CapsuleLib.h
> |   45 +-
>  MdeModulePkg/Include/Library/EdkiiSystemCapsuleLib.h
> |  152 ++
>  MdeModulePkg/Include/Library/FmpAuthenticationLib.h
> |   91 ++
>  MdeModulePkg/Include/Library/IniParsingLib.h
> |  153 ++
>  MdeModulePkg/Include/Library/PlatformFlashAccessLib.h
> |   59 +
>  MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.c
> | 1538 ++++++++++++++++++++
>  MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.inf
> |   82 ++
>  MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.uni
> |   22 +
>  MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleProcessLib.c
> |  517 +++++++
>  MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleReportLib.c
> |  447 ++++++
>  MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleRuntime.c
> |  112 ++
>  MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf
> |   85 ++
>  MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.uni
> |   22 +
>  MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.c
> |   47 +-
>  MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.c
> |  609 ++++++++
>  MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.inf
> |   55 +
>  MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.uni
> |   22 +
>  MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.c
> |  274 ++++
>  MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.inf
> |   47 +
>  MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.uni
> |   22 +
>  MdeModulePkg/Library/IniParsingLib/IniParsingLib.c
> | 1053 ++++++++++++++
>  MdeModulePkg/Library/IniParsingLib/IniParsingLib.inf
> |   42 +
>  MdeModulePkg/Library/IniParsingLib/IniParsingLib.uni
> |   22 +
>  MdeModulePkg/Library/PlatformFlashAccessLibNull/PlatformFlashAccessLibNull.c
> |   54 +
>  MdeModulePkg/Library/PlatformFlashAccessLibNull/PlatformFlashAccessLibNull.inf
> |   40 +
>  MdeModulePkg/Library/PlatformFlashAccessLibNull/PlatformFlashAccessLibNull.uni
> |   21 +
>  MdeModulePkg/MdeModulePkg.dec
> |  106 ++
>  MdeModulePkg/MdeModulePkg.dsc
> |   24 +
>  MdeModulePkg/Universal/EsrtDxe/EsrtDxe.inf
> |    3 +-
>  MdeModulePkg/Universal/EsrtDxe/EsrtImpl.c
> |   37 +-
>  MdeModulePkg/Universal/RecoveryModuleLoadPei/ParseConfigProfile.c
> |  158 ++
>  MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPei.c
> |  746 ++++++++++
>  MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPei.h
> |   44 +
>  MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPei.inf
> |   71 +
>  MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPei.uni
> |   21 +
>  MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPeiExtra.uni
> |   20 +
>  MdeModulePkg/Universal/SystemBiosUpdate/ParseConfigProfile.c
> |  219 +++
>  MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosDxe.h
> |  393 +++++
>  MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosMainDxe.c
> |  484 ++++++
>  MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosMainSetImage.c
> |  453 ++++++
>  MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosMainSetImageDummy.c
> |   90 ++
>  MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxe.inf
> |   66 +
>  MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxe.uni
> |   21 +
>  MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxeExtra.uni
> |   20 +
>  MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxe.inf
> |   70 +
>  MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxe.uni
> |   21 +
>  MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxeExtra.uni
> |   20 +
>
> QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLi
> bDxe.c   |  200 +++
>
> QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLi
> bDxe.inf |   52 +
>  QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/SpiFlashDevice.c
> |  336 +++++
>  QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/SpiFlashDevice.h
> |  186 +++
>  QuarkPlatformPkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptor.aslc
> |   88 ++
>  QuarkPlatformPkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptor.inf
> |   45 +
>  QuarkPlatformPkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptorPei.c
> |   66 +
>  QuarkPlatformPkg/Feature/Capsule/SystemBiosUpdateConfig/SystemBiosUpdateConfig.ini
> |   62 +
>  QuarkPlatformPkg/Library/PlatformBootManagerLib/PlatformBootManager.c
> |   95 +-
>  QuarkPlatformPkg/Library/PlatformBootManagerLib/PlatformBootManager.h
> |    8 +-
>  QuarkPlatformPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf
> |    8 +-
>  QuarkPlatformPkg/Platform/Pei/PlatformInit/MemoryCallback.c
> |    3 +-
>  QuarkPlatformPkg/Quark.dsc
> |   61 +-
>  QuarkPlatformPkg/Quark.fdf
> |   53 +
>  QuarkPlatformPkg/QuarkCapsule.dsc
> |   44 +
>  QuarkPlatformPkg/QuarkCapsule.fdf
> |   82 ++
>  QuarkPlatformPkg/QuarkMin.dsc
> |    7 +-
>  SecurityPkg/Library/FmpAuthenticationPkcs7Lib/FmpAuthenticationPkcs7Lib.c
> |  144 ++
>  SecurityPkg/Library/FmpAuthenticationPkcs7Lib/FmpAuthenticationPkcs7Lib.inf
> |   52 +
>  SecurityPkg/Library/FmpAuthenticationPkcs7Lib/FmpAuthenticationPkcs7Lib.uni
> |   26 +
>
> SecurityPkg/Library/FmpAuthenticationRsa2048Sha256Lib/FmpAuthenticationRsa2048Sha256L
> ib.c     |  286 ++++
>
> SecurityPkg/Library/FmpAuthenticationRsa2048Sha256Lib/FmpAuthenticationRsa2048Sha256L
> ib.inf   |   53 +
>
> SecurityPkg/Library/FmpAuthenticationRsa2048Sha256Lib/FmpAuthenticationRsa2048Sha256L
> ib.uni   |   26 +
>  SecurityPkg/SecurityPkg.dec
> |    6 +
>  SecurityPkg/SecurityPkg.dsc
> |    3 +
>  UefiCpuPkg/Application/MicrocodeCapsuleApp/AppSupport.c
> |  480 ++++++
>  UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.c
> |  283 ++++
>  UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.inf
> |   62 +
>  UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.uni
> |   22 +
>  UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleAppExtra.uni
> |   19 +
>  UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleDump.c
> |  171 +++
>  UefiCpuPkg/Include/Guid/MicrocodeFmp.h
> |   21 +
>  UefiCpuPkg/Include/Library/MicrocodeFlashAccessLib.h
> |   39 +
>  UefiCpuPkg/Library/MicrocodeFlashAccessLibNull/MicrocodeFlashAccessLibNull.c
> |   42 +
>  UefiCpuPkg/Library/MicrocodeFlashAccessLibNull/MicrocodeFlashAccessLibNull.inf
> |   40 +
>  UefiCpuPkg/Library/MicrocodeFlashAccessLibNull/MicrocodeFlashAccessLibNull.uni
> |   21 +
>  UefiCpuPkg/MicrocodeUpdate/MicrocodeFmp.c
> |  641 ++++++++
>  UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.c
> |  775 ++++++++++
>  UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.h
> |  299 ++++
>  UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.inf
> |   68 +
>  UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdateDxe.uni
> |   21 +
>  UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdateDxeExtra.uni
> |   20 +
>  UefiCpuPkg/UefiCpuPkg.dec
> |    7 +
>  UefiCpuPkg/UefiCpuPkg.dsc
> |    3 +
>
> Vlv2TbltDevicePkg/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessL
> ib.c     |  192 +++
>
> Vlv2TbltDevicePkg/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessL
> ib.inf   |   47 +
>  Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptor.aslc
> |   86 ++
>  Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptor.inf
> |   45 +
>  Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptorPei.c
> |   66 +
>  Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosUpdateConfig/SystemBiosUpdateConfig.ini
> |   72 +
>
> Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosUpdateConfig/SystemBiosUpdateConfigGcc.in
> i        |   72 +
>  Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLib.c
> |  156 +-
>  Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLib.inf
> |    8 +-
>  Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLibDxe.c
> |   62 +
>  Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLibDxe.inf
> |   49 +
>  Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLibDxeRuntimeSmm.c
> |  188 +++
>  Vlv2TbltDevicePkg/Library/FlashDeviceLib/SpiChipDefinitions.h
> |    5 +-
>  Vlv2TbltDevicePkg/Library/PlatformBdsLib/BdsPlatform.c
> |  117 +-
>  Vlv2TbltDevicePkg/Library/PlatformBdsLib/PlatformBdsLib.inf
> |    2 +
>  Vlv2TbltDevicePkg/PlatformCapsule.dsc
> |   44 +
>  Vlv2TbltDevicePkg/PlatformCapsule.fdf
> |   81 ++
>  Vlv2TbltDevicePkg/PlatformCapsuleGcc.fdf
> |   81 ++
>  Vlv2TbltDevicePkg/PlatformPkg.fdf
> |  132 +-
>  Vlv2TbltDevicePkg/PlatformPkgConfig.dsc
> |    3 +-
>  Vlv2TbltDevicePkg/PlatformPkgGcc.fdf
> |  132 +-
>  Vlv2TbltDevicePkg/PlatformPkgGccX64.dsc
> |   70 +-
>  Vlv2TbltDevicePkg/PlatformPkgIA32.dsc
> |   70 +-
>  Vlv2TbltDevicePkg/PlatformPkgX64.dsc
> |   70 +-
>  Vlv2TbltDevicePkg/bld_vlv.bat
> |    8 +-
>  124 files changed, 17848 insertions(+), 384 deletions(-)
>  create mode 100644 MdeModulePkg/Application/CapsuleApp/AppSupport.c
>  create mode 100644 MdeModulePkg/Application/CapsuleApp/CapsuleApp.c
>  create mode 100644 MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf
>  create mode 100644 MdeModulePkg/Application/CapsuleApp/CapsuleApp.uni
>  create mode 100644 MdeModulePkg/Application/CapsuleApp/CapsuleAppExtra.uni
>  create mode 100644 MdeModulePkg/Application/CapsuleApp/CapsuleDump.c
>  create mode 100644 MdeModulePkg/Include/Guid/EdkiiSystemFmpCapsule.h
>  create mode 100644 MdeModulePkg/Include/Library/EdkiiSystemCapsuleLib.h
>  create mode 100644 MdeModulePkg/Include/Library/FmpAuthenticationLib.h
>  create mode 100644 MdeModulePkg/Include/Library/IniParsingLib.h
>  create mode 100644 MdeModulePkg/Include/Library/PlatformFlashAccessLib.h
>  create mode 100644 MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.c
>  create mode 100644 MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.inf
>  create mode 100644 MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.uni
>  create mode 100644 MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleProcessLib.c
>  create mode 100644 MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleReportLib.c
>  create mode 100644 MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleRuntime.c
>  create mode 100644 MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf
>  create mode 100644 MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.uni
>  create mode 100644
> MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.c
>  create mode 100644
> MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.inf
>  create mode 100644
> MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.uni
>  create mode 100644 MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.c
>  create mode 100644
> MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.inf
>  create mode 100644
> MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.uni
>  create mode 100644 MdeModulePkg/Library/IniParsingLib/IniParsingLib.c
>  create mode 100644 MdeModulePkg/Library/IniParsingLib/IniParsingLib.inf
>  create mode 100644 MdeModulePkg/Library/IniParsingLib/IniParsingLib.uni
>  create mode 100644
> MdeModulePkg/Library/PlatformFlashAccessLibNull/PlatformFlashAccessLibNull.c
>  create mode 100644
> MdeModulePkg/Library/PlatformFlashAccessLibNull/PlatformFlashAccessLibNull.inf
>  create mode 100644
> MdeModulePkg/Library/PlatformFlashAccessLibNull/PlatformFlashAccessLibNull.uni
>  create mode 100644 MdeModulePkg/Universal/RecoveryModuleLoadPei/ParseConfigProfile.c
>  create mode 100644
> MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPei.c
>  create mode 100644
> MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPei.h
>  create mode 100644
> MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPei.inf
>  create mode 100644
> MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPei.uni
>  create mode 100644
> MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPeiExtra.uni
>  create mode 100644 MdeModulePkg/Universal/SystemBiosUpdate/ParseConfigProfile.c
>  create mode 100644 MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosDxe.h
>  create mode 100644 MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosMainDxe.c
>  create mode 100644 MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosMainSetImage.c
>  create mode 100644
> MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosMainSetImageDummy.c
>  create mode 100644 MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxe.inf
>  create mode 100644 MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxe.uni
>  create mode 100644
> MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxeExtra.uni
>  create mode 100644 MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxe.inf
>  create mode 100644 MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxe.uni
>  create mode 100644
> MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxeExtra.uni
>  create mode 100644
> QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLi
> bDxe.c
>  create mode 100644
> QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLi
> bDxe.inf
>  create mode 100644
> QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/SpiFlashDevice.c
>  create mode 100644
> QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/SpiFlashDevice.h
>  create mode 100644
> QuarkPlatformPkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptor.aslc
>  create mode 100644
> QuarkPlatformPkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptor.inf
>  create mode 100644
> QuarkPlatformPkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptorPei.c
>  create mode 100644
> QuarkPlatformPkg/Feature/Capsule/SystemBiosUpdateConfig/SystemBiosUpdateConfig.ini
>  create mode 100644 QuarkPlatformPkg/QuarkCapsule.dsc
>  create mode 100644 QuarkPlatformPkg/QuarkCapsule.fdf
>  create mode 100644
> SecurityPkg/Library/FmpAuthenticationPkcs7Lib/FmpAuthenticationPkcs7Lib.c
>  create mode 100644
> SecurityPkg/Library/FmpAuthenticationPkcs7Lib/FmpAuthenticationPkcs7Lib.inf
>  create mode 100644
> SecurityPkg/Library/FmpAuthenticationPkcs7Lib/FmpAuthenticationPkcs7Lib.uni
>  create mode 100644
> SecurityPkg/Library/FmpAuthenticationRsa2048Sha256Lib/FmpAuthenticationRsa2048Sha256L
> ib.c
>  create mode 100644
> SecurityPkg/Library/FmpAuthenticationRsa2048Sha256Lib/FmpAuthenticationRsa2048Sha256L
> ib.inf
>  create mode 100644
> SecurityPkg/Library/FmpAuthenticationRsa2048Sha256Lib/FmpAuthenticationRsa2048Sha256L
> ib.uni
>  create mode 100644 UefiCpuPkg/Application/MicrocodeCapsuleApp/AppSupport.c
>  create mode 100644 UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.c
>  create mode 100644
> UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.inf
>  create mode 100644
> UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.uni
>  create mode 100644
> UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleAppExtra.uni
>  create mode 100644 UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleDump.c
>  create mode 100644 UefiCpuPkg/Include/Guid/MicrocodeFmp.h
>  create mode 100644 UefiCpuPkg/Include/Library/MicrocodeFlashAccessLib.h
>  create mode 100644
> UefiCpuPkg/Library/MicrocodeFlashAccessLibNull/MicrocodeFlashAccessLibNull.c
>  create mode 100644
> UefiCpuPkg/Library/MicrocodeFlashAccessLibNull/MicrocodeFlashAccessLibNull.inf
>  create mode 100644
> UefiCpuPkg/Library/MicrocodeFlashAccessLibNull/MicrocodeFlashAccessLibNull.uni
>  create mode 100644 UefiCpuPkg/MicrocodeUpdate/MicrocodeFmp.c
>  create mode 100644 UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.c
>  create mode 100644 UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.h
>  create mode 100644 UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.inf
>  create mode 100644 UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdateDxe.uni
>  create mode 100644 UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdateDxeExtra.uni
>  create mode 100644
> Vlv2TbltDevicePkg/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessL
> ib.c
>  create mode 100644
> Vlv2TbltDevicePkg/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessL
> ib.inf
>  create mode 100644
> Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptor.aslc
>  create mode 100644
> Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptor.inf
>  create mode 100644
> Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptorPei.c
>  create mode 100644
> Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosUpdateConfig/SystemBiosUpdateConfig.ini
>  create mode 100644
> Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosUpdateConfig/SystemBiosUpdateConfigGcc.in
> i
>  create mode 100644 Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLibDxe.c
>  create mode 100644 Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLibDxe.inf
>  create mode 100644
> Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLibDxeRuntimeSmm.c
>  create mode 100644 Vlv2TbltDevicePkg/PlatformCapsule.dsc
>  create mode 100644 Vlv2TbltDevicePkg/PlatformCapsule.fdf
>  create mode 100644 Vlv2TbltDevicePkg/PlatformCapsuleGcc.fdf
>
> --
> 2.7.4.windows.1
>
> _______________________________________________
> edk2-devel mailing list
> edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>
> https://lists.01.org/mailman/listinfo/edk2-devel


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

* Re: [PATCH 42/45] Vlv2TbltDevicePkg/PlatformBootManager: Add capsule/recovery handling.
  2016-09-21  6:45 ` [PATCH 42/45] Vlv2TbltDevicePkg/PlatformBootManager: Add capsule/recovery handling Jiewen Yao
@ 2016-09-22  2:40   ` Wei, David
  0 siblings, 0 replies; 83+ messages in thread
From: Wei, David @ 2016-09-22  2:40 UTC (permalink / raw)
  To: Yao, Jiewen, edk2-devel@lists.01.org
  Cc: Tian, Feng, Zeng, Star, Kinney, Michael D, Gao, Liming,
	Zhang, Chao B, Wei, David

Reviewed-by: David Wei <david.wei@intel.com> 

Thanks,
David  Wei                                 


-----Original Message-----
From: Yao, Jiewen 
Sent: Wednesday, September 21, 2016 2:45 PM
To: edk2-devel@lists.01.org
Cc: Wei, David <david.wei@intel.com>; Tian, Feng <feng.tian@intel.com>; Zeng, Star <star.zeng@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: [PATCH 42/45] Vlv2TbltDevicePkg/PlatformBootManager: Add capsule/recovery handling.

Add capsule and recovery boot path handling in platform BDS.

Cc: David Wei <david.wei@intel.com>
Cc: Feng Tian <feng.tian@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Chao Zhang <chao.b.zhang@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
---
 Vlv2TbltDevicePkg/Library/PlatformBdsLib/BdsPlatform.c      | 117 ++++++++++----------
 Vlv2TbltDevicePkg/Library/PlatformBdsLib/PlatformBdsLib.inf |   2 +
 2 files changed, 60 insertions(+), 59 deletions(-)

diff --git a/Vlv2TbltDevicePkg/Library/PlatformBdsLib/BdsPlatform.c b/Vlv2TbltDevicePkg/Library/PlatformBdsLib/BdsPlatform.c
index 02e4616..580d774 100644
--- a/Vlv2TbltDevicePkg/Library/PlatformBdsLib/BdsPlatform.c
+++ b/Vlv2TbltDevicePkg/Library/PlatformBdsLib/BdsPlatform.c
@@ -1,15 +1,15 @@
 /** @file
 
   Copyright (c) 2004  - 2016, Intel Corporation. All rights reserved.<BR>
-                                                                                   

-  This program and the accompanying materials are licensed and made available under

-  the terms and conditions of the BSD License that accompanies this distribution.  

-  The full text of the license may be found at                                     

-  http://opensource.org/licenses/bsd-license.php.                                  

-                                                                                   

-  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,            

-  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.    

-                                                                                   

+                                                                                   
+  This program and the accompanying materials are licensed and made available under
+  the terms and conditions of the BSD License that accompanies this distribution.  
+  The full text of the license may be found at                                     
+  http://opensource.org/licenses/bsd-license.php.                                  
+                                                                                   
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,            
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.    
+                                                                                   
 
 
 Module Name:
@@ -45,6 +45,9 @@ Abstract:
 #include <Library/GenericBdsLib/String.h>
 #include <Library/NetLib.h>
 
+#include <Library/CapsuleLib.h>
+#include <Protocol/EsrtManagement.h>
+
 EFI_GUID *ConnectDriverTable[] = {
   &gEfiMmioDeviceProtocolGuid,
   &gEfiI2cMasterProtocolGuid,
@@ -181,6 +184,11 @@ InstallReadyToLock (
                     );
     ASSERT_EFI_ERROR (Status);
 
+    //
+    // Signal EndOfDxe PI Event
+    //
+    EfiEventGroupSignal (&gEfiEndOfDxeEventGroupGuid);
+
     Handle = NULL;
     Status = gBS->InstallProtocolInterface (
                     &Handle,
@@ -226,11 +234,6 @@ PlatformBdsInit (
   EFI_STATUS  Status;
   EFI_EVENT   ShellImageEvent;
   EFI_GUID    ShellEnvProtocol = SHELL_ENVIRONMENT_INTERFACE_PROTOCOL;
-  
-  //
-  // Signal EndOfDxe PI Event
-  //
-  EfiEventGroupSignal (&gEfiEndOfDxeEventGroupGuid);
 
   #ifdef __GNUC__
   SerialPortWrite((UINT8 *)">>>>BdsEntry[GCC]\r\n", 19);
@@ -1585,7 +1588,7 @@ EFIAPI
 PlatformBdsPolicyBehavior (
   IN OUT LIST_ENTRY                  *DriverOptionList,
   IN OUT LIST_ENTRY                  *BootOptionList,
-  IN PROCESS_CAPSULES                ProcessCapsules,
+  IN PROCESS_CAPSULES                BdsProcessCapsules,
   IN BASEM_MEMORY_TEST               BaseMemoryTest
   )
 {
@@ -1594,11 +1597,8 @@ PlatformBdsPolicyBehavior (
   EFI_BOOT_MODE                      BootMode;
   BOOLEAN                            DeferredImageExist;
   UINTN                              Index;
-  CHAR16                             CapsuleVarName[36];
-  CHAR16                             *TempVarName;
   SYSTEM_CONFIGURATION               SystemConfiguration;
   UINTN                              VarSize;
-  BOOLEAN                            SetVariableFlag;
   PLATFORM_PCI_DEVICE_PATH           *EmmcBootDevPath;
   EFI_GLOBAL_NVS_AREA_PROTOCOL       *GlobalNvsArea;
   EFI_HANDLE                         FvProtocolHandle;
@@ -1612,13 +1612,14 @@ PlatformBdsPolicyBehavior (
   BOOLEAN                            IsFirstBoot;
   UINT16                             *BootOrder;
   UINTN                              BootOrderSize;
+  ESRT_MANAGEMENT_PROTOCOL           *EsrtManagement;
 
   Timeout = PcdGet16 (PcdPlatformBootTimeOut);
   if (Timeout > 10 ) {
     //we think the Timeout variable is corrupted
     Timeout = 10;
   }
-  	
+
   VarSize = sizeof(SYSTEM_CONFIGURATION);
   Status = gRT->GetVariable(
                   NORMAL_SETUP_NAME,
@@ -1639,7 +1640,7 @@ PlatformBdsPolicyBehavior (
               &SystemConfiguration
               );
     ASSERT_EFI_ERROR (Status);
-  }  
+  }
 
   //
   // Load the driver option as the driver option list
@@ -1652,37 +1653,6 @@ PlatformBdsPolicyBehavior (
   BootMode = GetBootModeHob();
 
   //
-  // Clear all the capsule variables CapsuleUpdateData, CapsuleUpdateData1, CapsuleUpdateData2...
-  // as early as possible which will avoid the next time boot after the capsule update
-  // will still into the capsule loop
-  //
-  StrCpy (CapsuleVarName, EFI_CAPSULE_VARIABLE_NAME);
-  TempVarName = CapsuleVarName + StrLen (CapsuleVarName);
-  Index = 0;
-  SetVariableFlag = TRUE;
-  while (SetVariableFlag) {
-    if (Index > 0) {
-      UnicodeValueToString (TempVarName, 0, Index, 0);
-    }
-    Status = gRT->SetVariable (
-                    CapsuleVarName,
-                    &gEfiCapsuleVendorGuid,
-                    EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS |
-                    EFI_VARIABLE_BOOTSERVICE_ACCESS,
-                    0,
-                    (VOID *)NULL
-                    );
-    if (EFI_ERROR (Status)) {
-      //
-      // There is no capsule variables, quit
-      //
-      SetVariableFlag = FALSE;
-      continue;
-    }
-    Index++;
-  }
-
-  //
   // No deferred images exist by default
   //
   DeferredImageExist = FALSE;
@@ -1733,6 +1703,11 @@ PlatformBdsPolicyBehavior (
     }
   }
 
+  Status = gBS->LocateProtocol(&gEsrtManagementProtocolGuid, NULL, (VOID **)&EsrtManagement);
+  if (EFI_ERROR(Status)) {
+    EsrtManagement = NULL;
+  }
+
   switch (BootMode) {
 
   case BOOT_WITH_MINIMAL_CONFIGURATION:
@@ -1822,13 +1797,18 @@ PlatformBdsPolicyBehavior (
     #ifdef FTPM_ENABLE
     TrEEPhysicalPresenceLibProcessRequest(NULL);
     #endif
+
+    if (EsrtManagement != NULL) {
+      EsrtManagement->LockEsrtRepository();
+    }
+
     //
     // Close boot script and install ready to lock
     //
     InstallReadyToLock ();
 
     //
-    // Give one chance to enter the setup if we 
+    // Give one chance to enter the setup if we
     // select Gummiboot "Reboot Into Firmware Interface" and Fast Boot is enabled.
     //
     BootIntoFirmwareInterface();
@@ -1863,6 +1843,10 @@ PlatformBdsPolicyBehavior (
       }
     }
 
+    if (EsrtManagement != NULL) {
+      EsrtManagement->LockEsrtRepository();
+    }
+
     //
     // Close boot script and install ready to lock
     //
@@ -1887,6 +1871,16 @@ PlatformBdsPolicyBehavior (
     //
     PlatformBdsConnectConsole (gPlatformConsole);
     PlatformBdsDiagnostics (EXTENSIVE, FALSE, BaseMemoryTest);
+
+    DEBUG((EFI_D_INFO, "ProcessCapsules Before EndOfDxe......\n"));
+    ProcessCapsules ();
+    DEBUG((EFI_D_INFO, "ProcessCapsules Done\n"));
+
+    //
+    // Close boot script and install ready to lock
+    //
+    InstallReadyToLock ();
+
     BdsLibConnectAll ();
 
     //
@@ -1903,12 +1897,13 @@ PlatformBdsPolicyBehavior (
       }
     }
 
-    //
-    // Close boot script and install ready to lock
-    //
-    InstallReadyToLock ();
+    if (EsrtManagement != NULL) {
+      EsrtManagement->SyncEsrtFmp();
+    }
 
-    ProcessCapsules (BOOT_ON_FLASH_UPDATE);
+    DEBUG((EFI_D_INFO, "ProcessCapsules After ConnectAll......\n"));
+    ProcessCapsules();
+    DEBUG((EFI_D_INFO, "ProcessCapsules Done\n"));
     break;
 
   case BOOT_IN_RECOVERY_MODE:
@@ -2012,6 +2007,10 @@ FULL_CONFIGURATION:
    #ifdef FTPM_ENABLE
    TrEEPhysicalPresenceLibProcessRequest(NULL);
    #endif
+
+    if (EsrtManagement != NULL) {
+      EsrtManagement->SyncEsrtFmp();
+    }
     //
     // Close boot script and install ready to lock
     //
@@ -2029,7 +2028,7 @@ FULL_CONFIGURATION:
     PlatformBdsEnterFrontPageWithHotKey (Timeout, FALSE);
 
 	//
-	// Give one chance to enter the setup if we 
+	// Give one chance to enter the setup if we
 	// select Gummiboot "Reboot Into Firmware Interface"
 	//
 	BootIntoFirmwareInterface();
@@ -2047,7 +2046,7 @@ FULL_CONFIGURATION:
       return;
     }
 
-    
+
     break;
   }
 
diff --git a/Vlv2TbltDevicePkg/Library/PlatformBdsLib/PlatformBdsLib.inf b/Vlv2TbltDevicePkg/Library/PlatformBdsLib/PlatformBdsLib.inf
index c64bab9..ce7c426 100644
--- a/Vlv2TbltDevicePkg/Library/PlatformBdsLib/PlatformBdsLib.inf
+++ b/Vlv2TbltDevicePkg/Library/PlatformBdsLib/PlatformBdsLib.inf
@@ -72,6 +72,7 @@
   FileHandleLib
   S3BootScriptLib
   SerialPortLib
+  CapsuleLib
 
 [Protocols]
   gEfiFirmwareVolume2ProtocolGuid
@@ -90,6 +91,7 @@
   gEfiMmioDeviceProtocolGuid
   gEfiI2cMasterProtocolGuid
   gEfiI2cHostProtocolGuid
+  gEsrtManagementProtocolGuid
 
 [Guids]
   gEfiMemoryTypeInformationGuid
-- 
2.7.4.windows.1



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

* Re: [PATCH 00/45] Add capsule update and recovery sample.
  2016-09-21  6:44 [PATCH 00/45] Add capsule update and recovery sample Jiewen Yao
                   ` (45 preceding siblings ...)
  2016-09-21 16:35 ` [PATCH 00/45] Add capsule update and recovery sample Kinney, Michael D
@ 2016-09-23  3:18 ` Gao, Liming
  2016-09-24  6:42   ` Yao, Jiewen
  2016-09-27  3:16 ` Gao, Liming
  2016-09-28  8:05 ` Yao, Jiewen
  48 siblings, 1 reply; 83+ messages in thread
From: Gao, Liming @ 2016-09-23  3:18 UTC (permalink / raw)
  To: Yao, Jiewen, edk2-devel@lists.01.org
  Cc: Tian, Feng, Zeng, Star, Kinney, Michael D, Fan, Jeff,
	Zhang, Chao B

Jiewen:
  In MdeModulePkg, the below INF files have wrong PPI/Protocol/PCD usages. Please correct them. 
MdeModulePkg\Universal\SystemBiosUpdate\SystemBiosReportDxe.inf
MdeModulePkg\Universal\RecoveryModuleLoadPei\RecoveryModuleLoadPei.inf
MdeModulePkg\Universal\SystemBiosUpdate\SystemBiosUpdateDxe.inf

Thanks
Liming
> -----Original Message-----
> From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of
> Jiewen Yao
> Sent: Wednesday, September 21, 2016 2:45 PM
> To: edk2-devel@lists.01.org
> Cc: Tian, Feng <feng.tian@intel.com>; Gao, Liming <liming.gao@intel.com>;
> Zeng, Star <star.zeng@intel.com>; Kinney, Michael D
> <michael.d.kinney@intel.com>; Fan, Jeff <jeff.fan@intel.com>; Zhang, Chao
> B <chao.b.zhang@intel.com>
> Subject: [edk2] [PATCH 00/45] Add capsule update and recovery sample.
> 
> This series patch provides sample on how to do signed capsule update
> and recovery in EDKII.
> 
> This series patch is also checked into git@github.com:jyao1/edk2.git.
> 
> The feature includes:
> 1) Define EDKII signed system BIOS capsule format.
> 2) Provide EDKII signed system BIOS update sample.
> 3) Provide EDKII signed recovery sample.
> 4) Provide Microcode update sample for X86 system.
> 5) Update Quark to use new capsule/recovery solution.
> 6) Update Vlv2(MinnowMax) to use new capsule/recovery solution.
> 
> The signed capsule/recovery solution is in MdeModulePkg.
> The capsule in IntelFrameworkModulePkg is deprecated.
> The Microcode update solution is in UefiCpuPkg.
> 
> Cc: Feng Tian <feng.tian@intel.com>
> Cc: Star Zeng <star.zeng@intel.com>
> Cc: Michael D Kinney <michael.d.kinney@intel.com>
> Cc: Liming Gao <liming.gao@intel.com>
> Cc: Chao Zhang <chao.b.zhang@intel.com>
> Cc: Jeff Fan <jeff.fan@intel.com>
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
> 
> 
> Jiewen Yao (45):
>   MdeModulePkg/Include: Add EDKII system FMP capsule header.
>   MdeModulePkg/Include: Add EdkiiSystemCapsuleLib definition.
>   MdeModulePkg/Include: Add FmpAuthenticationLib header.
>   MdeModulePkg/Include: Add IniParsingLib header.
>   MdeModulePkg/Include: Add PlatformFlashAccessLib header.
>   MdeModulePkg/CapsuleLib: Add ProcessCapsules() API.
>   MdeModulePkg/MdeModulePkg.dec: Add capsule related definition.
>   MdeModulePkg/IniParsingLib: Add InitParsingLib instance.
>   MdeModulePkg/FmpAuthenticationLib: Add FmpAuthenticationLib instance.
>   MdeModulePkg/DxeCapsuleLibFmp: Add DxeCapsuleLibFmp instance.
>   MdeModulePkg/DxeCapsuleLibNull: Add ProcessCapsules() interface.
>   MdeModulePkg/EdkiiSystemCapsuleLib: Add EdkiiSystemCapsuleLib
>     instance.
>   MdeModulePkg/PlatformFlashAccessLib: Add NULL PlatformFlashAccessLib.
>   MdeModulePkg/Esrt: Add ESRT_FW_TYPE_SYSTEMFIRMWARE check.
>   MdeModulePkg/SystemBiosUpdate: Add SystemBiosUpdate component.
>   MdeModulePkg/RecoveryModuleLoadPei: Add RecoveryModuleLoadPei.
>   MdeModulePkg/CapsuleApp: Add CapsuleApp application.
>   MdeModulePkg/MdeModulePkg.dsc: Add capsule related component.
>   IntelFrameworkModulePkg/DxeCapsuleLib: Add ProcessCapsules()
>     interface.
>   SecurityPkg/SecurityPkg.dec: Add PcdPkcs7CertBuffer PCD.
>   SecurityPkg/FmpAuthenticationPkcs7Lib: Add PKCS7 NULL class for FMP.
>   SecurityPkg/FmpAuthenticationRsa2048Sha256Lib: Add NULL class for FMP.
>   SecurityPkg/SecurityPkg.dsc: Add FmpAuthentication*Lib.
>   UefiCpuPkg/Include: Add Microcode FMP definition.
>   UefiCpuPkg/Include: Add MicrocodeFlashAccessLib header.
>   UefiCpuPkg/UefiCpuPkg.dec: Add Microcode capsule related definition.
>   UefiCpuPkg/MicrocodeUpdate: Add MicrocodeUpdate component.
>   UefiCpuPkg/MicrocodeFlashAccessLib: Add NULL MicrocodeFlashAccessLib.
>   UefiCpuPkg/MicrocodeCapsuleApp: Add MicrocodeCapsuleApp application.
>   UefiCpuPkg/UefiCpuPkg.dsc: Add MicrocodeCapsule related component.
>   QuarkPlatformPkg/PlatformFlashAccessLib: Add instance for capsule
>     update.
>   QuarkPlatformPkg/SystemBiosDescriptor: Add Descriptor for capsule
>     update.
>   QuarkPlatformPkg/SystemBiosUpdateConfig: Add capsule config file.
>   QuarkPlatformPkg/PlatformInit: Remove recovery PPI installation.
>   QuarkPlatformPkg/PlatformBootManager: Add capsule/recovery handling.
>   QuarkPlatformPkg/dsc/fdf: Add capsule/recovery support.
>   QuarkPlatformPkg/dsc/fdf: add capsule generation DSC/FDF.
>   Vlv2TbltDevicePkg/PlatformFlashAccessLib: Add instance for capsule
>     update.
>   Vlv2TbltDevicePkg/SystemBiosDescriptor: Add Descriptor for capsule
>     update.
>   Vlv2TbltDevicePkg/SystemBiosUpdateConfig: Add capsule config file.
>   Vlv2TbltDevicePkg/FlashDeviceLib: Add DXE flash device lib.
>   Vlv2TbltDevicePkg/PlatformBootManager: Add capsule/recovery handling.
>   Vlv2TbltDevicePkg/dsc/fdf: Add capsule/recovery support.
>   Vlv2TbltDevicePkg/dsc/fdf: add capsule generation DSC/FDF.
>   Vlv2TbltDevicePkg/bat: add capsule generation in bat.
> 
>  IntelFrameworkModulePkg/Library/DxeCapsuleLib/DxeCapsuleLib.c
> |   39 +-
>  MdeModulePkg/Application/CapsuleApp/AppSupport.c
> |  480 ++++++
>  MdeModulePkg/Application/CapsuleApp/CapsuleApp.c
> | 1047 +++++++++++++
>  MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf
> |   71 +
>  MdeModulePkg/Application/CapsuleApp/CapsuleApp.uni
> |   22 +
>  MdeModulePkg/Application/CapsuleApp/CapsuleAppExtra.uni
> |   19 +
>  MdeModulePkg/Application/CapsuleApp/CapsuleDump.c
> |  840 +++++++++++
>  MdeModulePkg/Include/Guid/EdkiiSystemFmpCapsule.h
> |  110 ++
>  MdeModulePkg/Include/Library/CapsuleLib.h                                                     |
> 45 +-
>  MdeModulePkg/Include/Library/EdkiiSystemCapsuleLib.h
> |  152 ++
>  MdeModulePkg/Include/Library/FmpAuthenticationLib.h
> |   91 ++
>  MdeModulePkg/Include/Library/IniParsingLib.h                                                  |
> 153 ++
>  MdeModulePkg/Include/Library/PlatformFlashAccessLib.h
> |   59 +
>  MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.c
> | 1538 ++++++++++++++++++++
>  MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.inf
> |   82 ++
>  MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.uni
> |   22 +
>  MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleProcessLib.c
> |  517 +++++++
>  MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleReportLib.c
> |  447 ++++++
>  MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleRuntime.c
> |  112 ++
>  MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf
> |   85 ++
>  MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.uni
> |   22 +
>  MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.c
> |   47 +-
>  MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.c
> |  609 ++++++++
>  MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.inf
> |   55 +
>  MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.uni
> |   22 +
>  MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.c
> |  274 ++++
>  MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.inf
> |   47 +
>  MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.uni
> |   22 +
>  MdeModulePkg/Library/IniParsingLib/IniParsingLib.c                                            |
> 1053 ++++++++++++++
>  MdeModulePkg/Library/IniParsingLib/IniParsingLib.inf                                          |
> 42 +
>  MdeModulePkg/Library/IniParsingLib/IniParsingLib.uni                                          |
> 22 +
> 
> MdeModulePkg/Library/PlatformFlashAccessLibNull/PlatformFlashAccessLib
> Null.c                  |   54 +
> 
> MdeModulePkg/Library/PlatformFlashAccessLibNull/PlatformFlashAccessLib
> Null.inf                |   40 +
> 
> MdeModulePkg/Library/PlatformFlashAccessLibNull/PlatformFlashAccessLib
> Null.uni                |   21 +
>  MdeModulePkg/MdeModulePkg.dec                                                                 |  106
> ++
>  MdeModulePkg/MdeModulePkg.dsc                                                                 |   24 +
>  MdeModulePkg/Universal/EsrtDxe/EsrtDxe.inf                                                    |
> 3 +-
>  MdeModulePkg/Universal/EsrtDxe/EsrtImpl.c                                                     |
> 37 +-
>  MdeModulePkg/Universal/RecoveryModuleLoadPei/ParseConfigProfile.c
> |  158 ++
> 
> MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadP
> ei.c                          |  746 ++++++++++
> 
> MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadP
> ei.h                          |   44 +
> 
> MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadP
> ei.inf                        |   71 +
> 
> MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadP
> ei.uni                        |   21 +
> 
> MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadP
> eiExtra.uni                   |   20 +
>  MdeModulePkg/Universal/SystemBiosUpdate/ParseConfigProfile.c
> |  219 +++
>  MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosDxe.h
> |  393 +++++
>  MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosMainDxe.c
> |  484 ++++++
>  MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosMainSetImage.c
> |  453 ++++++
> 
> MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosMainSetImageDu
> mmy.c                         |   90 ++
>  MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxe.inf
> |   66 +
>  MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxe.uni
> |   21 +
> 
> MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxeExtra.u
> ni                          |   20 +
>  MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxe.inf
> |   70 +
>  MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxe.uni
> |   21 +
> 
> MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxeExtra.
> uni                          |   20 +
> 
> QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/Platfor
> mFlashAccessLibDxe.c   |  200 +++
> 
> QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/Platfor
> mFlashAccessLibDxe.inf |   52 +
> 
> QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/SpiFlash
> Device.c              |  336 +++++
> 
> QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/SpiFlash
> Device.h              |  186 +++
> 
> QuarkPlatformPkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescr
> iptor.aslc               |   88 ++
> 
> QuarkPlatformPkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescr
> iptor.inf                |   45 +
> 
> QuarkPlatformPkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescr
> iptorPei.c               |   66 +
> 
> QuarkPlatformPkg/Feature/Capsule/SystemBiosUpdateConfig/SystemBiosU
> pdateConfig.ini            |   62 +
> 
> QuarkPlatformPkg/Library/PlatformBootManagerLib/PlatformBootManager.
> c                         |   95 +-
> 
> QuarkPlatformPkg/Library/PlatformBootManagerLib/PlatformBootManager.
> h                         |    8 +-
> 
> QuarkPlatformPkg/Library/PlatformBootManagerLib/PlatformBootManagerL
> ib.inf                    |    8 +-
>  QuarkPlatformPkg/Platform/Pei/PlatformInit/MemoryCallback.c
> |    3 +-
>  QuarkPlatformPkg/Quark.dsc                                                                    |   61 +-
>  QuarkPlatformPkg/Quark.fdf                                                                    |   53 +
>  QuarkPlatformPkg/QuarkCapsule.dsc                                                             |   44 +
>  QuarkPlatformPkg/QuarkCapsule.fdf                                                             |   82 ++
>  QuarkPlatformPkg/QuarkMin.dsc                                                                 |    7 +-
> 
> SecurityPkg/Library/FmpAuthenticationPkcs7Lib/FmpAuthenticationPkcs7Lib
> .c                     |  144 ++
> 
> SecurityPkg/Library/FmpAuthenticationPkcs7Lib/FmpAuthenticationPkcs7Lib
> .inf                   |   52 +
> 
> SecurityPkg/Library/FmpAuthenticationPkcs7Lib/FmpAuthenticationPkcs7Lib
> .uni                   |   26 +
> 
> SecurityPkg/Library/FmpAuthenticationRsa2048Sha256Lib/FmpAuthenticatio
> nRsa2048Sha256Lib.c     |  286 ++++
> 
> SecurityPkg/Library/FmpAuthenticationRsa2048Sha256Lib/FmpAuthenticatio
> nRsa2048Sha256Lib.inf   |   53 +
> 
> SecurityPkg/Library/FmpAuthenticationRsa2048Sha256Lib/FmpAuthenticatio
> nRsa2048Sha256Lib.uni   |   26 +
>  SecurityPkg/SecurityPkg.dec                                                                   |    6 +
>  SecurityPkg/SecurityPkg.dsc                                                                   |    3 +
>  UefiCpuPkg/Application/MicrocodeCapsuleApp/AppSupport.c
> |  480 ++++++
>  UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.c
> |  283 ++++
>  UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.inf
> |   62 +
>  UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.uni
> |   22 +
> 
> UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleAppExtra.
> uni                       |   19 +
>  UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleDump.c
> |  171 +++
>  UefiCpuPkg/Include/Guid/MicrocodeFmp.h                                                        |   21
> +
>  UefiCpuPkg/Include/Library/MicrocodeFlashAccessLib.h
> |   39 +
> 
> UefiCpuPkg/Library/MicrocodeFlashAccessLibNull/MicrocodeFlashAccessLib
> Null.c                  |   42 +
> 
> UefiCpuPkg/Library/MicrocodeFlashAccessLibNull/MicrocodeFlashAccessLib
> Null.inf                |   40 +
> 
> UefiCpuPkg/Library/MicrocodeFlashAccessLibNull/MicrocodeFlashAccessLib
> Null.uni                |   21 +
>  UefiCpuPkg/MicrocodeUpdate/MicrocodeFmp.c                                                     |
> 641 ++++++++
>  UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.c
> |  775 ++++++++++
>  UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.h
> |  299 ++++
>  UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.inf
> |   68 +
>  UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdateDxe.uni
> |   21 +
>  UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdateDxeExtra.uni
> |   20 +
>  UefiCpuPkg/UefiCpuPkg.dec                                                                     |    7 +
>  UefiCpuPkg/UefiCpuPkg.dsc                                                                     |    3 +
> 
> Vlv2TbltDevicePkg/Feature/Capsule/Library/PlatformFlashAccessLib/Platfor
> mFlashAccessLib.c     |  192 +++
> 
> Vlv2TbltDevicePkg/Feature/Capsule/Library/PlatformFlashAccessLib/Platfor
> mFlashAccessLib.inf   |   47 +
> 
> Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescr
> iptor.aslc              |   86 ++
> 
> Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescr
> iptor.inf               |   45 +
> 
> Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescr
> iptorPei.c              |   66 +
> 
> Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosUpdateConfig/SystemBiosU
> pdateConfig.ini           |   72 +
> 
> Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosUpdateConfig/SystemBiosU
> pdateConfigGcc.ini        |   72 +
>  Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLib.c
> |  156 +-
>  Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLib.inf
> |    8 +-
>  Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLibDxe.c
> |   62 +
>  Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLibDxe.inf
> |   49 +
>  Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLibDxeRuntimeSmm.c
> |  188 +++
>  Vlv2TbltDevicePkg/Library/FlashDeviceLib/SpiChipDefinitions.h
> |    5 +-
>  Vlv2TbltDevicePkg/Library/PlatformBdsLib/BdsPlatform.c
> |  117 +-
>  Vlv2TbltDevicePkg/Library/PlatformBdsLib/PlatformBdsLib.inf
> |    2 +
>  Vlv2TbltDevicePkg/PlatformCapsule.dsc                                                         |   44 +
>  Vlv2TbltDevicePkg/PlatformCapsule.fdf                                                         |   81 ++
>  Vlv2TbltDevicePkg/PlatformCapsuleGcc.fdf                                                      |   81
> ++
>  Vlv2TbltDevicePkg/PlatformPkg.fdf                                                             |  132 +-
>  Vlv2TbltDevicePkg/PlatformPkgConfig.dsc                                                       |    3 +-
>  Vlv2TbltDevicePkg/PlatformPkgGcc.fdf                                                          |  132 +-
>  Vlv2TbltDevicePkg/PlatformPkgGccX64.dsc                                                       |   70
> +-
>  Vlv2TbltDevicePkg/PlatformPkgIA32.dsc                                                         |   70 +-
>  Vlv2TbltDevicePkg/PlatformPkgX64.dsc                                                          |   70 +-
>  Vlv2TbltDevicePkg/bld_vlv.bat                                                                 |    8 +-
>  124 files changed, 17848 insertions(+), 384 deletions(-)
>  create mode 100644
> MdeModulePkg/Application/CapsuleApp/AppSupport.c
>  create mode 100644 MdeModulePkg/Application/CapsuleApp/CapsuleApp.c
>  create mode 100644
> MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf
>  create mode 100644
> MdeModulePkg/Application/CapsuleApp/CapsuleApp.uni
>  create mode 100644
> MdeModulePkg/Application/CapsuleApp/CapsuleAppExtra.uni
>  create mode 100644
> MdeModulePkg/Application/CapsuleApp/CapsuleDump.c
>  create mode 100644
> MdeModulePkg/Include/Guid/EdkiiSystemFmpCapsule.h
>  create mode 100644
> MdeModulePkg/Include/Library/EdkiiSystemCapsuleLib.h
>  create mode 100644
> MdeModulePkg/Include/Library/FmpAuthenticationLib.h
>  create mode 100644 MdeModulePkg/Include/Library/IniParsingLib.h
>  create mode 100644
> MdeModulePkg/Include/Library/PlatformFlashAccessLib.h
>  create mode 100644
> MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.c
>  create mode 100644
> MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.inf
>  create mode 100644
> MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.uni
>  create mode 100644
> MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleProcessLib.c
>  create mode 100644
> MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleReportLib.c
>  create mode 100644
> MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleRuntime.c
>  create mode 100644
> MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf
>  create mode 100644
> MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.uni
>  create mode 100644
> MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.c
>  create mode 100644
> MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.inf
>  create mode 100644
> MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.uni
>  create mode 100644
> MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.c
>  create mode 100644
> MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.inf
>  create mode 100644
> MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.uni
>  create mode 100644 MdeModulePkg/Library/IniParsingLib/IniParsingLib.c
>  create mode 100644 MdeModulePkg/Library/IniParsingLib/IniParsingLib.inf
>  create mode 100644 MdeModulePkg/Library/IniParsingLib/IniParsingLib.uni
>  create mode 100644
> MdeModulePkg/Library/PlatformFlashAccessLibNull/PlatformFlashAccessLib
> Null.c
>  create mode 100644
> MdeModulePkg/Library/PlatformFlashAccessLibNull/PlatformFlashAccessLib
> Null.inf
>  create mode 100644
> MdeModulePkg/Library/PlatformFlashAccessLibNull/PlatformFlashAccessLib
> Null.uni
>  create mode 100644
> MdeModulePkg/Universal/RecoveryModuleLoadPei/ParseConfigProfile.c
>  create mode 100644
> MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadP
> ei.c
>  create mode 100644
> MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadP
> ei.h
>  create mode 100644
> MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadP
> ei.inf
>  create mode 100644
> MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadP
> ei.uni
>  create mode 100644
> MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadP
> eiExtra.uni
>  create mode 100644
> MdeModulePkg/Universal/SystemBiosUpdate/ParseConfigProfile.c
>  create mode 100644
> MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosDxe.h
>  create mode 100644
> MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosMainDxe.c
>  create mode 100644
> MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosMainSetImage.c
>  create mode 100644
> MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosMainSetImageDu
> mmy.c
>  create mode 100644
> MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxe.inf
>  create mode 100644
> MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxe.uni
>  create mode 100644
> MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxeExtra.u
> ni
>  create mode 100644
> MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxe.inf
>  create mode 100644
> MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxe.uni
>  create mode 100644
> MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxeExtra.
> uni
>  create mode 100644
> QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/Platfor
> mFlashAccessLibDxe.c
>  create mode 100644
> QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/Platfor
> mFlashAccessLibDxe.inf
>  create mode 100644
> QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/SpiFlash
> Device.c
>  create mode 100644
> QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/SpiFlash
> Device.h
>  create mode 100644
> QuarkPlatformPkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescr
> iptor.aslc
>  create mode 100644
> QuarkPlatformPkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescr
> iptor.inf
>  create mode 100644
> QuarkPlatformPkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescr
> iptorPei.c
>  create mode 100644
> QuarkPlatformPkg/Feature/Capsule/SystemBiosUpdateConfig/SystemBiosU
> pdateConfig.ini
>  create mode 100644 QuarkPlatformPkg/QuarkCapsule.dsc
>  create mode 100644 QuarkPlatformPkg/QuarkCapsule.fdf
>  create mode 100644
> SecurityPkg/Library/FmpAuthenticationPkcs7Lib/FmpAuthenticationPkcs7Lib
> .c
>  create mode 100644
> SecurityPkg/Library/FmpAuthenticationPkcs7Lib/FmpAuthenticationPkcs7Lib
> .inf
>  create mode 100644
> SecurityPkg/Library/FmpAuthenticationPkcs7Lib/FmpAuthenticationPkcs7Lib
> .uni
>  create mode 100644
> SecurityPkg/Library/FmpAuthenticationRsa2048Sha256Lib/FmpAuthenticatio
> nRsa2048Sha256Lib.c
>  create mode 100644
> SecurityPkg/Library/FmpAuthenticationRsa2048Sha256Lib/FmpAuthenticatio
> nRsa2048Sha256Lib.inf
>  create mode 100644
> SecurityPkg/Library/FmpAuthenticationRsa2048Sha256Lib/FmpAuthenticatio
> nRsa2048Sha256Lib.uni
>  create mode 100644
> UefiCpuPkg/Application/MicrocodeCapsuleApp/AppSupport.c
>  create mode 100644
> UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.c
>  create mode 100644
> UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.inf
>  create mode 100644
> UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.uni
>  create mode 100644
> UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleAppExtra.
> uni
>  create mode 100644
> UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleDump.c
>  create mode 100644 UefiCpuPkg/Include/Guid/MicrocodeFmp.h
>  create mode 100644
> UefiCpuPkg/Include/Library/MicrocodeFlashAccessLib.h
>  create mode 100644
> UefiCpuPkg/Library/MicrocodeFlashAccessLibNull/MicrocodeFlashAccessLib
> Null.c
>  create mode 100644
> UefiCpuPkg/Library/MicrocodeFlashAccessLibNull/MicrocodeFlashAccessLib
> Null.inf
>  create mode 100644
> UefiCpuPkg/Library/MicrocodeFlashAccessLibNull/MicrocodeFlashAccessLib
> Null.uni
>  create mode 100644 UefiCpuPkg/MicrocodeUpdate/MicrocodeFmp.c
>  create mode 100644 UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.c
>  create mode 100644 UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.h
>  create mode 100644 UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.inf
>  create mode 100644
> UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdateDxe.uni
>  create mode 100644
> UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdateDxeExtra.uni
>  create mode 100644
> Vlv2TbltDevicePkg/Feature/Capsule/Library/PlatformFlashAccessLib/Platfor
> mFlashAccessLib.c
>  create mode 100644
> Vlv2TbltDevicePkg/Feature/Capsule/Library/PlatformFlashAccessLib/Platfor
> mFlashAccessLib.inf
>  create mode 100644
> Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescr
> iptor.aslc
>  create mode 100644
> Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescr
> iptor.inf
>  create mode 100644
> Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescr
> iptorPei.c
>  create mode 100644
> Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosUpdateConfig/SystemBiosU
> pdateConfig.ini
>  create mode 100644
> Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosUpdateConfig/SystemBiosU
> pdateConfigGcc.ini
>  create mode 100644
> Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLibDxe.c
>  create mode 100644
> Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLibDxe.inf
>  create mode 100644
> Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLibDxeRuntimeSmm.c
>  create mode 100644 Vlv2TbltDevicePkg/PlatformCapsule.dsc
>  create mode 100644 Vlv2TbltDevicePkg/PlatformCapsule.fdf
>  create mode 100644 Vlv2TbltDevicePkg/PlatformCapsuleGcc.fdf
> 
> --
> 2.7.4.windows.1
> 
> _______________________________________________
> edk2-devel mailing list
> edk2-devel@lists.01.org
> https://lists.01.org/mailman/listinfo/edk2-devel


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

* Re: [PATCH 00/45] Add capsule update and recovery sample.
  2016-09-23  3:18 ` Gao, Liming
@ 2016-09-24  6:42   ` Yao, Jiewen
  0 siblings, 0 replies; 83+ messages in thread
From: Yao, Jiewen @ 2016-09-24  6:42 UTC (permalink / raw)
  To: Gao, Liming, edk2-devel@lists.01.org
  Cc: Tian, Feng, Zeng, Star, Kinney, Michael D, Fan, Jeff,
	Zhang, Chao B

Thanks to catch that.

I just sent out 2 new patches to fix the INF issue, for easy code review.
They are also checked into git@github.com:jyao1/edk2.git<mailto:git@github.com:jyao1/edk2.git>.

Thank you
Yao Jiewen

From: Gao, Liming
Sent: Friday, September 23, 2016 11:18 AM
To: Yao, Jiewen <jiewen.yao@intel.com>; edk2-devel@lists.01.org
Cc: Tian, Feng <feng.tian@intel.com>; Zeng, Star <star.zeng@intel.com>; Kinney, Michael D <michael.d.kinney@intel.com>; Fan, Jeff <jeff.fan@intel.com>; Zhang, Chao B <chao.b.zhang@intel.com>
Subject: RE: [edk2] [PATCH 00/45] Add capsule update and recovery sample.

Jiewen:
  In MdeModulePkg, the below INF files have wrong PPI/Protocol/PCD usages. Please correct them.
MdeModulePkg\Universal\SystemBiosUpdate\SystemBiosReportDxe.inf
MdeModulePkg\Universal\RecoveryModuleLoadPei\RecoveryModuleLoadPei.inf
MdeModulePkg\Universal\SystemBiosUpdate\SystemBiosUpdateDxe.inf

Thanks
Liming
> -----Original Message-----
> From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of
> Jiewen Yao
> Sent: Wednesday, September 21, 2016 2:45 PM
> To: edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>
> Cc: Tian, Feng <feng.tian@intel.com<mailto:feng.tian@intel.com>>; Gao, Liming <liming.gao@intel.com<mailto:liming.gao@intel.com>>;
> Zeng, Star <star.zeng@intel.com<mailto:star.zeng@intel.com>>; Kinney, Michael D
> <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>; Fan, Jeff <jeff.fan@intel.com<mailto:jeff.fan@intel.com>>; Zhang, Chao
> B <chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com>>
> Subject: [edk2] [PATCH 00/45] Add capsule update and recovery sample.
>
> This series patch provides sample on how to do signed capsule update
> and recovery in EDKII.
>
> This series patch is also checked into git@github.com:jyao1/edk2.git<mailto:git@github.com:jyao1/edk2.git>.
>
> The feature includes:
> 1) Define EDKII signed system BIOS capsule format.
> 2) Provide EDKII signed system BIOS update sample.
> 3) Provide EDKII signed recovery sample.
> 4) Provide Microcode update sample for X86 system.
> 5) Update Quark to use new capsule/recovery solution.
> 6) Update Vlv2(MinnowMax) to use new capsule/recovery solution.
>
> The signed capsule/recovery solution is in MdeModulePkg.
> The capsule in IntelFrameworkModulePkg is deprecated.
> The Microcode update solution is in UefiCpuPkg.
>
> Cc: Feng Tian <feng.tian@intel.com<mailto:feng.tian@intel.com>>
> Cc: Star Zeng <star.zeng@intel.com<mailto:star.zeng@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 Zhang <chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com>>
> Cc: Jeff Fan <jeff.fan@intel.com<mailto:jeff.fan@intel.com>>
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Jiewen Yao <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>
>
>
> Jiewen Yao (45):
>   MdeModulePkg/Include: Add EDKII system FMP capsule header.
>   MdeModulePkg/Include: Add EdkiiSystemCapsuleLib definition.
>   MdeModulePkg/Include: Add FmpAuthenticationLib header.
>   MdeModulePkg/Include: Add IniParsingLib header.
>   MdeModulePkg/Include: Add PlatformFlashAccessLib header.
>   MdeModulePkg/CapsuleLib: Add ProcessCapsules() API.
>   MdeModulePkg/MdeModulePkg.dec: Add capsule related definition.
>   MdeModulePkg/IniParsingLib: Add InitParsingLib instance.
>   MdeModulePkg/FmpAuthenticationLib: Add FmpAuthenticationLib instance.
>   MdeModulePkg/DxeCapsuleLibFmp: Add DxeCapsuleLibFmp instance.
>   MdeModulePkg/DxeCapsuleLibNull: Add ProcessCapsules() interface.
>   MdeModulePkg/EdkiiSystemCapsuleLib: Add EdkiiSystemCapsuleLib
>     instance.
>   MdeModulePkg/PlatformFlashAccessLib: Add NULL PlatformFlashAccessLib.
>   MdeModulePkg/Esrt: Add ESRT_FW_TYPE_SYSTEMFIRMWARE check.
>   MdeModulePkg/SystemBiosUpdate: Add SystemBiosUpdate component.
>   MdeModulePkg/RecoveryModuleLoadPei: Add RecoveryModuleLoadPei.
>   MdeModulePkg/CapsuleApp: Add CapsuleApp application.
>   MdeModulePkg/MdeModulePkg.dsc: Add capsule related component.
>   IntelFrameworkModulePkg/DxeCapsuleLib: Add ProcessCapsules()
>     interface.
>   SecurityPkg/SecurityPkg.dec: Add PcdPkcs7CertBuffer PCD.
>   SecurityPkg/FmpAuthenticationPkcs7Lib: Add PKCS7 NULL class for FMP.
>   SecurityPkg/FmpAuthenticationRsa2048Sha256Lib: Add NULL class for FMP.
>   SecurityPkg/SecurityPkg.dsc: Add FmpAuthentication*Lib.
>   UefiCpuPkg/Include: Add Microcode FMP definition.
>   UefiCpuPkg/Include: Add MicrocodeFlashAccessLib header.
>   UefiCpuPkg/UefiCpuPkg.dec: Add Microcode capsule related definition.
>   UefiCpuPkg/MicrocodeUpdate: Add MicrocodeUpdate component.
>   UefiCpuPkg/MicrocodeFlashAccessLib: Add NULL MicrocodeFlashAccessLib.
>   UefiCpuPkg/MicrocodeCapsuleApp: Add MicrocodeCapsuleApp application.
>   UefiCpuPkg/UefiCpuPkg.dsc: Add MicrocodeCapsule related component.
>   QuarkPlatformPkg/PlatformFlashAccessLib: Add instance for capsule
>     update.
>   QuarkPlatformPkg/SystemBiosDescriptor: Add Descriptor for capsule
>     update.
>   QuarkPlatformPkg/SystemBiosUpdateConfig: Add capsule config file.
>   QuarkPlatformPkg/PlatformInit: Remove recovery PPI installation.
>   QuarkPlatformPkg/PlatformBootManager: Add capsule/recovery handling.
>   QuarkPlatformPkg/dsc/fdf: Add capsule/recovery support.
>   QuarkPlatformPkg/dsc/fdf: add capsule generation DSC/FDF.
>   Vlv2TbltDevicePkg/PlatformFlashAccessLib: Add instance for capsule
>     update.
>   Vlv2TbltDevicePkg/SystemBiosDescriptor: Add Descriptor for capsule
>     update.
>   Vlv2TbltDevicePkg/SystemBiosUpdateConfig: Add capsule config file.
>   Vlv2TbltDevicePkg/FlashDeviceLib: Add DXE flash device lib.
>   Vlv2TbltDevicePkg/PlatformBootManager: Add capsule/recovery handling.
>   Vlv2TbltDevicePkg/dsc/fdf: Add capsule/recovery support.
>   Vlv2TbltDevicePkg/dsc/fdf: add capsule generation DSC/FDF.
>   Vlv2TbltDevicePkg/bat: add capsule generation in bat.
>
>  IntelFrameworkModulePkg/Library/DxeCapsuleLib/DxeCapsuleLib.c
> |   39 +-
>  MdeModulePkg/Application/CapsuleApp/AppSupport.c
> |  480 ++++++
>  MdeModulePkg/Application/CapsuleApp/CapsuleApp.c
> | 1047 +++++++++++++
>  MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf
> |   71 +
>  MdeModulePkg/Application/CapsuleApp/CapsuleApp.uni
> |   22 +
>  MdeModulePkg/Application/CapsuleApp/CapsuleAppExtra.uni
> |   19 +
>  MdeModulePkg/Application/CapsuleApp/CapsuleDump.c
> |  840 +++++++++++
>  MdeModulePkg/Include/Guid/EdkiiSystemFmpCapsule.h
> |  110 ++
>  MdeModulePkg/Include/Library/CapsuleLib.h                                                     |
> 45 +-
>  MdeModulePkg/Include/Library/EdkiiSystemCapsuleLib.h
> |  152 ++
>  MdeModulePkg/Include/Library/FmpAuthenticationLib.h
> |   91 ++
>  MdeModulePkg/Include/Library/IniParsingLib.h                                                  |
> 153 ++
>  MdeModulePkg/Include/Library/PlatformFlashAccessLib.h
> |   59 +
>  MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.c
> | 1538 ++++++++++++++++++++
>  MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.inf
> |   82 ++
>  MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.uni
> |   22 +
>  MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleProcessLib.c
> |  517 +++++++
>  MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleReportLib.c
> |  447 ++++++
>  MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleRuntime.c
> |  112 ++
>  MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf
> |   85 ++
>  MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.uni
> |   22 +
>  MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.c
> |   47 +-
>  MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.c
> |  609 ++++++++
>  MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.inf
> |   55 +
>  MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.uni
> |   22 +
>  MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.c
> |  274 ++++
>  MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.inf
> |   47 +
>  MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.uni
> |   22 +
>  MdeModulePkg/Library/IniParsingLib/IniParsingLib.c                                            |
> 1053 ++++++++++++++
>  MdeModulePkg/Library/IniParsingLib/IniParsingLib.inf                                          |
> 42 +
>  MdeModulePkg/Library/IniParsingLib/IniParsingLib.uni                                          |
> 22 +
>
> MdeModulePkg/Library/PlatformFlashAccessLibNull/PlatformFlashAccessLib
> Null.c                  |   54 +
>
> MdeModulePkg/Library/PlatformFlashAccessLibNull/PlatformFlashAccessLib
> Null.inf                |   40 +
>
> MdeModulePkg/Library/PlatformFlashAccessLibNull/PlatformFlashAccessLib
> Null.uni                |   21 +
>  MdeModulePkg/MdeModulePkg.dec                                                                 |  106
> ++
>  MdeModulePkg/MdeModulePkg.dsc                                                                 |   24 +
>  MdeModulePkg/Universal/EsrtDxe/EsrtDxe.inf                                                    |
> 3 +-
>  MdeModulePkg/Universal/EsrtDxe/EsrtImpl.c                                                     |
> 37 +-
>  MdeModulePkg/Universal/RecoveryModuleLoadPei/ParseConfigProfile.c
> |  158 ++
>
> MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadP
> ei.c                          |  746 ++++++++++
>
> MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadP
> ei.h                          |   44 +
>
> MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadP
> ei.inf                        |   71 +
>
> MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadP
> ei.uni                        |   21 +
>
> MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadP
> eiExtra.uni                   |   20 +
>  MdeModulePkg/Universal/SystemBiosUpdate/ParseConfigProfile.c
> |  219 +++
>  MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosDxe.h
> |  393 +++++
>  MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosMainDxe.c
> |  484 ++++++
>  MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosMainSetImage.c
> |  453 ++++++
>
> MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosMainSetImageDu
> mmy.c                         |   90 ++
>  MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxe.inf
> |   66 +
>  MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxe.uni
> |   21 +
>
> MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxeExtra.u
> ni                          |   20 +
>  MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxe.inf
> |   70 +
>  MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxe.uni
> |   21 +
>
> MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxeExtra.
> uni                          |   20 +
>
> QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/Platfor
> mFlashAccessLibDxe.c   |  200 +++
>
> QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/Platfor
> mFlashAccessLibDxe.inf |   52 +
>
> QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/SpiFlash
> Device.c              |  336 +++++
>
> QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/SpiFlash
> Device.h              |  186 +++
>
> QuarkPlatformPkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescr
> iptor.aslc               |   88 ++
>
> QuarkPlatformPkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescr
> iptor.inf                |   45 +
>
> QuarkPlatformPkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescr
> iptorPei.c               |   66 +
>
> QuarkPlatformPkg/Feature/Capsule/SystemBiosUpdateConfig/SystemBiosU
> pdateConfig.ini            |   62 +
>
> QuarkPlatformPkg/Library/PlatformBootManagerLib/PlatformBootManager.
> c                         |   95 +-
>
> QuarkPlatformPkg/Library/PlatformBootManagerLib/PlatformBootManager.
> h                         |    8 +-
>
> QuarkPlatformPkg/Library/PlatformBootManagerLib/PlatformBootManagerL
> ib.inf                    |    8 +-
>  QuarkPlatformPkg/Platform/Pei/PlatformInit/MemoryCallback.c
> |    3 +-
>  QuarkPlatformPkg/Quark.dsc                                                                    |   61 +-
>  QuarkPlatformPkg/Quark.fdf                                                                    |   53 +
>  QuarkPlatformPkg/QuarkCapsule.dsc                                                             |   44 +
>  QuarkPlatformPkg/QuarkCapsule.fdf                                                             |   82 ++
>  QuarkPlatformPkg/QuarkMin.dsc                                                                 |    7 +-
>
> SecurityPkg/Library/FmpAuthenticationPkcs7Lib/FmpAuthenticationPkcs7Lib
> .c                     |  144 ++
>
> SecurityPkg/Library/FmpAuthenticationPkcs7Lib/FmpAuthenticationPkcs7Lib
> .inf                   |   52 +
>
> SecurityPkg/Library/FmpAuthenticationPkcs7Lib/FmpAuthenticationPkcs7Lib
> .uni                   |   26 +
>
> SecurityPkg/Library/FmpAuthenticationRsa2048Sha256Lib/FmpAuthenticatio
> nRsa2048Sha256Lib.c     |  286 ++++
>
> SecurityPkg/Library/FmpAuthenticationRsa2048Sha256Lib/FmpAuthenticatio
> nRsa2048Sha256Lib.inf   |   53 +
>
> SecurityPkg/Library/FmpAuthenticationRsa2048Sha256Lib/FmpAuthenticatio
> nRsa2048Sha256Lib.uni   |   26 +
>  SecurityPkg/SecurityPkg.dec                                                                   |    6 +
>  SecurityPkg/SecurityPkg.dsc                                                                   |    3 +
>  UefiCpuPkg/Application/MicrocodeCapsuleApp/AppSupport.c
> |  480 ++++++
>  UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.c
> |  283 ++++
>  UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.inf
> |   62 +
>  UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.uni
> |   22 +
>
> UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleAppExtra.
> uni                       |   19 +
>  UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleDump.c
> |  171 +++
>  UefiCpuPkg/Include/Guid/MicrocodeFmp.h                                                        |   21
> +
>  UefiCpuPkg/Include/Library/MicrocodeFlashAccessLib.h
> |   39 +
>
> UefiCpuPkg/Library/MicrocodeFlashAccessLibNull/MicrocodeFlashAccessLib
> Null.c                  |   42 +
>
> UefiCpuPkg/Library/MicrocodeFlashAccessLibNull/MicrocodeFlashAccessLib
> Null.inf                |   40 +
>
> UefiCpuPkg/Library/MicrocodeFlashAccessLibNull/MicrocodeFlashAccessLib
> Null.uni                |   21 +
>  UefiCpuPkg/MicrocodeUpdate/MicrocodeFmp.c                                                     |
> 641 ++++++++
>  UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.c
> |  775 ++++++++++
>  UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.h
> |  299 ++++
>  UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.inf
> |   68 +
>  UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdateDxe.uni
> |   21 +
>  UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdateDxeExtra.uni
> |   20 +
>  UefiCpuPkg/UefiCpuPkg.dec                                                                     |    7 +
>  UefiCpuPkg/UefiCpuPkg.dsc                                                                     |    3 +
>
> Vlv2TbltDevicePkg/Feature/Capsule/Library/PlatformFlashAccessLib/Platfor
> mFlashAccessLib.c     |  192 +++
>
> Vlv2TbltDevicePkg/Feature/Capsule/Library/PlatformFlashAccessLib/Platfor
> mFlashAccessLib.inf   |   47 +
>
> Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescr
> iptor.aslc              |   86 ++
>
> Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescr
> iptor.inf               |   45 +
>
> Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescr
> iptorPei.c              |   66 +
>
> Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosUpdateConfig/SystemBiosU
> pdateConfig.ini           |   72 +
>
> Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosUpdateConfig/SystemBiosU
> pdateConfigGcc.ini        |   72 +
>  Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLib.c
> |  156 +-
>  Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLib.inf
> |    8 +-
>  Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLibDxe.c
> |   62 +
>  Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLibDxe.inf
> |   49 +
>  Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLibDxeRuntimeSmm.c
> |  188 +++
>  Vlv2TbltDevicePkg/Library/FlashDeviceLib/SpiChipDefinitions.h
> |    5 +-
>  Vlv2TbltDevicePkg/Library/PlatformBdsLib/BdsPlatform.c
> |  117 +-
>  Vlv2TbltDevicePkg/Library/PlatformBdsLib/PlatformBdsLib.inf
> |    2 +
>  Vlv2TbltDevicePkg/PlatformCapsule.dsc                                                         |   44 +
>  Vlv2TbltDevicePkg/PlatformCapsule.fdf                                                         |   81 ++
>  Vlv2TbltDevicePkg/PlatformCapsuleGcc.fdf                                                      |   81
> ++
>  Vlv2TbltDevicePkg/PlatformPkg.fdf                                                             |  132 +-
>  Vlv2TbltDevicePkg/PlatformPkgConfig.dsc                                                       |    3 +-
>  Vlv2TbltDevicePkg/PlatformPkgGcc.fdf                                                          |  132 +-
>  Vlv2TbltDevicePkg/PlatformPkgGccX64.dsc                                                       |   70
> +-
>  Vlv2TbltDevicePkg/PlatformPkgIA32.dsc                                                         |   70 +-
>  Vlv2TbltDevicePkg/PlatformPkgX64.dsc                                                          |   70 +-
>  Vlv2TbltDevicePkg/bld_vlv.bat                                                                 |    8 +-
>  124 files changed, 17848 insertions(+), 384 deletions(-)
>  create mode 100644
> MdeModulePkg/Application/CapsuleApp/AppSupport.c
>  create mode 100644 MdeModulePkg/Application/CapsuleApp/CapsuleApp.c
>  create mode 100644
> MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf
>  create mode 100644
> MdeModulePkg/Application/CapsuleApp/CapsuleApp.uni
>  create mode 100644
> MdeModulePkg/Application/CapsuleApp/CapsuleAppExtra.uni
>  create mode 100644
> MdeModulePkg/Application/CapsuleApp/CapsuleDump.c
>  create mode 100644
> MdeModulePkg/Include/Guid/EdkiiSystemFmpCapsule.h
>  create mode 100644
> MdeModulePkg/Include/Library/EdkiiSystemCapsuleLib.h
>  create mode 100644
> MdeModulePkg/Include/Library/FmpAuthenticationLib.h
>  create mode 100644 MdeModulePkg/Include/Library/IniParsingLib.h
>  create mode 100644
> MdeModulePkg/Include/Library/PlatformFlashAccessLib.h
>  create mode 100644
> MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.c
>  create mode 100644
> MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.inf
>  create mode 100644
> MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.uni
>  create mode 100644
> MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleProcessLib.c
>  create mode 100644
> MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleReportLib.c
>  create mode 100644
> MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleRuntime.c
>  create mode 100644
> MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf
>  create mode 100644
> MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.uni
>  create mode 100644
> MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.c
>  create mode 100644
> MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.inf
>  create mode 100644
> MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.uni
>  create mode 100644
> MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.c
>  create mode 100644
> MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.inf
>  create mode 100644
> MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.uni
>  create mode 100644 MdeModulePkg/Library/IniParsingLib/IniParsingLib.c
>  create mode 100644 MdeModulePkg/Library/IniParsingLib/IniParsingLib.inf
>  create mode 100644 MdeModulePkg/Library/IniParsingLib/IniParsingLib.uni
>  create mode 100644
> MdeModulePkg/Library/PlatformFlashAccessLibNull/PlatformFlashAccessLib
> Null.c
>  create mode 100644
> MdeModulePkg/Library/PlatformFlashAccessLibNull/PlatformFlashAccessLib
> Null.inf
>  create mode 100644
> MdeModulePkg/Library/PlatformFlashAccessLibNull/PlatformFlashAccessLib
> Null.uni
>  create mode 100644
> MdeModulePkg/Universal/RecoveryModuleLoadPei/ParseConfigProfile.c
>  create mode 100644
> MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadP
> ei.c
>  create mode 100644
> MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadP
> ei.h
>  create mode 100644
> MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadP
> ei.inf
>  create mode 100644
> MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadP
> ei.uni
>  create mode 100644
> MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadP
> eiExtra.uni
>  create mode 100644
> MdeModulePkg/Universal/SystemBiosUpdate/ParseConfigProfile.c
>  create mode 100644
> MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosDxe.h
>  create mode 100644
> MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosMainDxe.c
>  create mode 100644
> MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosMainSetImage.c
>  create mode 100644
> MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosMainSetImageDu
> mmy.c
>  create mode 100644
> MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxe.inf
>  create mode 100644
> MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxe.uni
>  create mode 100644
> MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxeExtra.u
> ni
>  create mode 100644
> MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxe.inf
>  create mode 100644
> MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxe.uni
>  create mode 100644
> MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxeExtra.
> uni
>  create mode 100644
> QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/Platfor
> mFlashAccessLibDxe.c
>  create mode 100644
> QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/Platfor
> mFlashAccessLibDxe.inf
>  create mode 100644
> QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/SpiFlash
> Device.c
>  create mode 100644
> QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/SpiFlash
> Device.h
>  create mode 100644
> QuarkPlatformPkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescr
> iptor.aslc
>  create mode 100644
> QuarkPlatformPkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescr
> iptor.inf
>  create mode 100644
> QuarkPlatformPkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescr
> iptorPei.c
>  create mode 100644
> QuarkPlatformPkg/Feature/Capsule/SystemBiosUpdateConfig/SystemBiosU
> pdateConfig.ini
>  create mode 100644 QuarkPlatformPkg/QuarkCapsule.dsc
>  create mode 100644 QuarkPlatformPkg/QuarkCapsule.fdf
>  create mode 100644
> SecurityPkg/Library/FmpAuthenticationPkcs7Lib/FmpAuthenticationPkcs7Lib
> .c
>  create mode 100644
> SecurityPkg/Library/FmpAuthenticationPkcs7Lib/FmpAuthenticationPkcs7Lib
> .inf
>  create mode 100644
> SecurityPkg/Library/FmpAuthenticationPkcs7Lib/FmpAuthenticationPkcs7Lib
> .uni
>  create mode 100644
> SecurityPkg/Library/FmpAuthenticationRsa2048Sha256Lib/FmpAuthenticatio
> nRsa2048Sha256Lib.c
>  create mode 100644
> SecurityPkg/Library/FmpAuthenticationRsa2048Sha256Lib/FmpAuthenticatio
> nRsa2048Sha256Lib.inf
>  create mode 100644
> SecurityPkg/Library/FmpAuthenticationRsa2048Sha256Lib/FmpAuthenticatio
> nRsa2048Sha256Lib.uni
>  create mode 100644
> UefiCpuPkg/Application/MicrocodeCapsuleApp/AppSupport.c
>  create mode 100644
> UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.c
>  create mode 100644
> UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.inf
>  create mode 100644
> UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.uni
>  create mode 100644
> UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleAppExtra.
> uni
>  create mode 100644
> UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleDump.c
>  create mode 100644 UefiCpuPkg/Include/Guid/MicrocodeFmp.h
>  create mode 100644
> UefiCpuPkg/Include/Library/MicrocodeFlashAccessLib.h
>  create mode 100644
> UefiCpuPkg/Library/MicrocodeFlashAccessLibNull/MicrocodeFlashAccessLib
> Null.c
>  create mode 100644
> UefiCpuPkg/Library/MicrocodeFlashAccessLibNull/MicrocodeFlashAccessLib
> Null.inf
>  create mode 100644
> UefiCpuPkg/Library/MicrocodeFlashAccessLibNull/MicrocodeFlashAccessLib
> Null.uni
>  create mode 100644 UefiCpuPkg/MicrocodeUpdate/MicrocodeFmp.c
>  create mode 100644 UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.c
>  create mode 100644 UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.h
>  create mode 100644 UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.inf
>  create mode 100644
> UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdateDxe.uni
>  create mode 100644
> UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdateDxeExtra.uni
>  create mode 100644
> Vlv2TbltDevicePkg/Feature/Capsule/Library/PlatformFlashAccessLib/Platfor
> mFlashAccessLib.c
>  create mode 100644
> Vlv2TbltDevicePkg/Feature/Capsule/Library/PlatformFlashAccessLib/Platfor
> mFlashAccessLib.inf
>  create mode 100644
> Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescr
> iptor.aslc
>  create mode 100644
> Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescr
> iptor.inf
>  create mode 100644
> Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescr
> iptorPei.c
>  create mode 100644
> Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosUpdateConfig/SystemBiosU
> pdateConfig.ini
>  create mode 100644
> Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosUpdateConfig/SystemBiosU
> pdateConfigGcc.ini
>  create mode 100644
> Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLibDxe.c
>  create mode 100644
> Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLibDxe.inf
>  create mode 100644
> Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLibDxeRuntimeSmm.c
>  create mode 100644 Vlv2TbltDevicePkg/PlatformCapsule.dsc
>  create mode 100644 Vlv2TbltDevicePkg/PlatformCapsule.fdf
>  create mode 100644 Vlv2TbltDevicePkg/PlatformCapsuleGcc.fdf
>
> --
> 2.7.4.windows.1
>
> _______________________________________________
> edk2-devel mailing list
> edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>
> https://lists.01.org/mailman/listinfo/edk2-devel


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

* Re: [PATCH 00/45] Add capsule update and recovery sample.
  2016-09-21  6:44 [PATCH 00/45] Add capsule update and recovery sample Jiewen Yao
                   ` (46 preceding siblings ...)
  2016-09-23  3:18 ` Gao, Liming
@ 2016-09-27  3:16 ` Gao, Liming
  2016-09-28  8:05 ` Yao, Jiewen
  48 siblings, 0 replies; 83+ messages in thread
From: Gao, Liming @ 2016-09-27  3:16 UTC (permalink / raw)
  To: Yao, Jiewen, edk2-devel@lists.01.org
  Cc: Tian, Feng, Zeng, Star, Kinney, Michael D, Fan, Jeff,
	Zhang, Chao B

MdeModulePkg patches are good to me. Reviewed-by: Liming Gao <liming.gao@intel.com>

> -----Original Message-----
> From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of
> Jiewen Yao
> Sent: Wednesday, September 21, 2016 2:45 PM
> To: edk2-devel@lists.01.org
> Cc: Tian, Feng <feng.tian@intel.com>; Gao, Liming <liming.gao@intel.com>;
> Zeng, Star <star.zeng@intel.com>; Kinney, Michael D
> <michael.d.kinney@intel.com>; Fan, Jeff <jeff.fan@intel.com>; Zhang, Chao
> B <chao.b.zhang@intel.com>
> Subject: [edk2] [PATCH 00/45] Add capsule update and recovery sample.
> 
> This series patch provides sample on how to do signed capsule update
> and recovery in EDKII.
> 
> This series patch is also checked into git@github.com:jyao1/edk2.git.
> 
> The feature includes:
> 1) Define EDKII signed system BIOS capsule format.
> 2) Provide EDKII signed system BIOS update sample.
> 3) Provide EDKII signed recovery sample.
> 4) Provide Microcode update sample for X86 system.
> 5) Update Quark to use new capsule/recovery solution.
> 6) Update Vlv2(MinnowMax) to use new capsule/recovery solution.
> 
> The signed capsule/recovery solution is in MdeModulePkg.
> The capsule in IntelFrameworkModulePkg is deprecated.
> The Microcode update solution is in UefiCpuPkg.
> 
> Cc: Feng Tian <feng.tian@intel.com>
> Cc: Star Zeng <star.zeng@intel.com>
> Cc: Michael D Kinney <michael.d.kinney@intel.com>
> Cc: Liming Gao <liming.gao@intel.com>
> Cc: Chao Zhang <chao.b.zhang@intel.com>
> Cc: Jeff Fan <jeff.fan@intel.com>
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
> 
> 
> Jiewen Yao (45):
>   MdeModulePkg/Include: Add EDKII system FMP capsule header.
>   MdeModulePkg/Include: Add EdkiiSystemCapsuleLib definition.
>   MdeModulePkg/Include: Add FmpAuthenticationLib header.
>   MdeModulePkg/Include: Add IniParsingLib header.
>   MdeModulePkg/Include: Add PlatformFlashAccessLib header.
>   MdeModulePkg/CapsuleLib: Add ProcessCapsules() API.
>   MdeModulePkg/MdeModulePkg.dec: Add capsule related definition.
>   MdeModulePkg/IniParsingLib: Add InitParsingLib instance.
>   MdeModulePkg/FmpAuthenticationLib: Add FmpAuthenticationLib instance.
>   MdeModulePkg/DxeCapsuleLibFmp: Add DxeCapsuleLibFmp instance.
>   MdeModulePkg/DxeCapsuleLibNull: Add ProcessCapsules() interface.
>   MdeModulePkg/EdkiiSystemCapsuleLib: Add EdkiiSystemCapsuleLib
>     instance.
>   MdeModulePkg/PlatformFlashAccessLib: Add NULL PlatformFlashAccessLib.
>   MdeModulePkg/Esrt: Add ESRT_FW_TYPE_SYSTEMFIRMWARE check.
>   MdeModulePkg/SystemBiosUpdate: Add SystemBiosUpdate component.
>   MdeModulePkg/RecoveryModuleLoadPei: Add RecoveryModuleLoadPei.
>   MdeModulePkg/CapsuleApp: Add CapsuleApp application.
>   MdeModulePkg/MdeModulePkg.dsc: Add capsule related component.
>   IntelFrameworkModulePkg/DxeCapsuleLib: Add ProcessCapsules()
>     interface.
>   SecurityPkg/SecurityPkg.dec: Add PcdPkcs7CertBuffer PCD.
>   SecurityPkg/FmpAuthenticationPkcs7Lib: Add PKCS7 NULL class for FMP.
>   SecurityPkg/FmpAuthenticationRsa2048Sha256Lib: Add NULL class for FMP.
>   SecurityPkg/SecurityPkg.dsc: Add FmpAuthentication*Lib.
>   UefiCpuPkg/Include: Add Microcode FMP definition.
>   UefiCpuPkg/Include: Add MicrocodeFlashAccessLib header.
>   UefiCpuPkg/UefiCpuPkg.dec: Add Microcode capsule related definition.
>   UefiCpuPkg/MicrocodeUpdate: Add MicrocodeUpdate component.
>   UefiCpuPkg/MicrocodeFlashAccessLib: Add NULL MicrocodeFlashAccessLib.
>   UefiCpuPkg/MicrocodeCapsuleApp: Add MicrocodeCapsuleApp application.
>   UefiCpuPkg/UefiCpuPkg.dsc: Add MicrocodeCapsule related component.
>   QuarkPlatformPkg/PlatformFlashAccessLib: Add instance for capsule
>     update.
>   QuarkPlatformPkg/SystemBiosDescriptor: Add Descriptor for capsule
>     update.
>   QuarkPlatformPkg/SystemBiosUpdateConfig: Add capsule config file.
>   QuarkPlatformPkg/PlatformInit: Remove recovery PPI installation.
>   QuarkPlatformPkg/PlatformBootManager: Add capsule/recovery handling.
>   QuarkPlatformPkg/dsc/fdf: Add capsule/recovery support.
>   QuarkPlatformPkg/dsc/fdf: add capsule generation DSC/FDF.
>   Vlv2TbltDevicePkg/PlatformFlashAccessLib: Add instance for capsule
>     update.
>   Vlv2TbltDevicePkg/SystemBiosDescriptor: Add Descriptor for capsule
>     update.
>   Vlv2TbltDevicePkg/SystemBiosUpdateConfig: Add capsule config file.
>   Vlv2TbltDevicePkg/FlashDeviceLib: Add DXE flash device lib.
>   Vlv2TbltDevicePkg/PlatformBootManager: Add capsule/recovery handling.
>   Vlv2TbltDevicePkg/dsc/fdf: Add capsule/recovery support.
>   Vlv2TbltDevicePkg/dsc/fdf: add capsule generation DSC/FDF.
>   Vlv2TbltDevicePkg/bat: add capsule generation in bat.
> 
>  IntelFrameworkModulePkg/Library/DxeCapsuleLib/DxeCapsuleLib.c
> |   39 +-
>  MdeModulePkg/Application/CapsuleApp/AppSupport.c
> |  480 ++++++
>  MdeModulePkg/Application/CapsuleApp/CapsuleApp.c
> | 1047 +++++++++++++
>  MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf
> |   71 +
>  MdeModulePkg/Application/CapsuleApp/CapsuleApp.uni
> |   22 +
>  MdeModulePkg/Application/CapsuleApp/CapsuleAppExtra.uni
> |   19 +
>  MdeModulePkg/Application/CapsuleApp/CapsuleDump.c
> |  840 +++++++++++
>  MdeModulePkg/Include/Guid/EdkiiSystemFmpCapsule.h
> |  110 ++
>  MdeModulePkg/Include/Library/CapsuleLib.h                                                     |
> 45 +-
>  MdeModulePkg/Include/Library/EdkiiSystemCapsuleLib.h
> |  152 ++
>  MdeModulePkg/Include/Library/FmpAuthenticationLib.h
> |   91 ++
>  MdeModulePkg/Include/Library/IniParsingLib.h                                                  |
> 153 ++
>  MdeModulePkg/Include/Library/PlatformFlashAccessLib.h
> |   59 +
>  MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.c
> | 1538 ++++++++++++++++++++
>  MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.inf
> |   82 ++
>  MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.uni
> |   22 +
>  MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleProcessLib.c
> |  517 +++++++
>  MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleReportLib.c
> |  447 ++++++
>  MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleRuntime.c
> |  112 ++
>  MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf
> |   85 ++
>  MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.uni
> |   22 +
>  MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.c
> |   47 +-
>  MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.c
> |  609 ++++++++
>  MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.inf
> |   55 +
>  MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.uni
> |   22 +
>  MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.c
> |  274 ++++
>  MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.inf
> |   47 +
>  MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.uni
> |   22 +
>  MdeModulePkg/Library/IniParsingLib/IniParsingLib.c                                            |
> 1053 ++++++++++++++
>  MdeModulePkg/Library/IniParsingLib/IniParsingLib.inf                                          |
> 42 +
>  MdeModulePkg/Library/IniParsingLib/IniParsingLib.uni                                          |
> 22 +
> 
> MdeModulePkg/Library/PlatformFlashAccessLibNull/PlatformFlashAccessLib
> Null.c                  |   54 +
> 
> MdeModulePkg/Library/PlatformFlashAccessLibNull/PlatformFlashAccessLib
> Null.inf                |   40 +
> 
> MdeModulePkg/Library/PlatformFlashAccessLibNull/PlatformFlashAccessLib
> Null.uni                |   21 +
>  MdeModulePkg/MdeModulePkg.dec                                                                 |  106
> ++
>  MdeModulePkg/MdeModulePkg.dsc                                                                 |   24 +
>  MdeModulePkg/Universal/EsrtDxe/EsrtDxe.inf                                                    |
> 3 +-
>  MdeModulePkg/Universal/EsrtDxe/EsrtImpl.c                                                     |
> 37 +-
>  MdeModulePkg/Universal/RecoveryModuleLoadPei/ParseConfigProfile.c
> |  158 ++
> 
> MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadP
> ei.c                          |  746 ++++++++++
> 
> MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadP
> ei.h                          |   44 +
> 
> MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadP
> ei.inf                        |   71 +
> 
> MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadP
> ei.uni                        |   21 +
> 
> MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadP
> eiExtra.uni                   |   20 +
>  MdeModulePkg/Universal/SystemBiosUpdate/ParseConfigProfile.c
> |  219 +++
>  MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosDxe.h
> |  393 +++++
>  MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosMainDxe.c
> |  484 ++++++
>  MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosMainSetImage.c
> |  453 ++++++
> 
> MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosMainSetImageDu
> mmy.c                         |   90 ++
>  MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxe.inf
> |   66 +
>  MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxe.uni
> |   21 +
> 
> MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxeExtra.u
> ni                          |   20 +
>  MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxe.inf
> |   70 +
>  MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxe.uni
> |   21 +
> 
> MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxeExtra.
> uni                          |   20 +
> 
> QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/Platfor
> mFlashAccessLibDxe.c   |  200 +++
> 
> QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/Platfor
> mFlashAccessLibDxe.inf |   52 +
> 
> QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/SpiFlash
> Device.c              |  336 +++++
> 
> QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/SpiFlash
> Device.h              |  186 +++
> 
> QuarkPlatformPkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescr
> iptor.aslc               |   88 ++
> 
> QuarkPlatformPkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescr
> iptor.inf                |   45 +
> 
> QuarkPlatformPkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescr
> iptorPei.c               |   66 +
> 
> QuarkPlatformPkg/Feature/Capsule/SystemBiosUpdateConfig/SystemBiosU
> pdateConfig.ini            |   62 +
> 
> QuarkPlatformPkg/Library/PlatformBootManagerLib/PlatformBootManager.
> c                         |   95 +-
> 
> QuarkPlatformPkg/Library/PlatformBootManagerLib/PlatformBootManager.
> h                         |    8 +-
> 
> QuarkPlatformPkg/Library/PlatformBootManagerLib/PlatformBootManagerL
> ib.inf                    |    8 +-
>  QuarkPlatformPkg/Platform/Pei/PlatformInit/MemoryCallback.c
> |    3 +-
>  QuarkPlatformPkg/Quark.dsc                                                                    |   61 +-
>  QuarkPlatformPkg/Quark.fdf                                                                    |   53 +
>  QuarkPlatformPkg/QuarkCapsule.dsc                                                             |   44 +
>  QuarkPlatformPkg/QuarkCapsule.fdf                                                             |   82 ++
>  QuarkPlatformPkg/QuarkMin.dsc                                                                 |    7 +-
> 
> SecurityPkg/Library/FmpAuthenticationPkcs7Lib/FmpAuthenticationPkcs7Lib
> .c                     |  144 ++
> 
> SecurityPkg/Library/FmpAuthenticationPkcs7Lib/FmpAuthenticationPkcs7Lib
> .inf                   |   52 +
> 
> SecurityPkg/Library/FmpAuthenticationPkcs7Lib/FmpAuthenticationPkcs7Lib
> .uni                   |   26 +
> 
> SecurityPkg/Library/FmpAuthenticationRsa2048Sha256Lib/FmpAuthenticatio
> nRsa2048Sha256Lib.c     |  286 ++++
> 
> SecurityPkg/Library/FmpAuthenticationRsa2048Sha256Lib/FmpAuthenticatio
> nRsa2048Sha256Lib.inf   |   53 +
> 
> SecurityPkg/Library/FmpAuthenticationRsa2048Sha256Lib/FmpAuthenticatio
> nRsa2048Sha256Lib.uni   |   26 +
>  SecurityPkg/SecurityPkg.dec                                                                   |    6 +
>  SecurityPkg/SecurityPkg.dsc                                                                   |    3 +
>  UefiCpuPkg/Application/MicrocodeCapsuleApp/AppSupport.c
> |  480 ++++++
>  UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.c
> |  283 ++++
>  UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.inf
> |   62 +
>  UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.uni
> |   22 +
> 
> UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleAppExtra.
> uni                       |   19 +
>  UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleDump.c
> |  171 +++
>  UefiCpuPkg/Include/Guid/MicrocodeFmp.h                                                        |   21
> +
>  UefiCpuPkg/Include/Library/MicrocodeFlashAccessLib.h
> |   39 +
> 
> UefiCpuPkg/Library/MicrocodeFlashAccessLibNull/MicrocodeFlashAccessLib
> Null.c                  |   42 +
> 
> UefiCpuPkg/Library/MicrocodeFlashAccessLibNull/MicrocodeFlashAccessLib
> Null.inf                |   40 +
> 
> UefiCpuPkg/Library/MicrocodeFlashAccessLibNull/MicrocodeFlashAccessLib
> Null.uni                |   21 +
>  UefiCpuPkg/MicrocodeUpdate/MicrocodeFmp.c                                                     |
> 641 ++++++++
>  UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.c
> |  775 ++++++++++
>  UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.h
> |  299 ++++
>  UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.inf
> |   68 +
>  UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdateDxe.uni
> |   21 +
>  UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdateDxeExtra.uni
> |   20 +
>  UefiCpuPkg/UefiCpuPkg.dec                                                                     |    7 +
>  UefiCpuPkg/UefiCpuPkg.dsc                                                                     |    3 +
> 
> Vlv2TbltDevicePkg/Feature/Capsule/Library/PlatformFlashAccessLib/Platfor
> mFlashAccessLib.c     |  192 +++
> 
> Vlv2TbltDevicePkg/Feature/Capsule/Library/PlatformFlashAccessLib/Platfor
> mFlashAccessLib.inf   |   47 +
> 
> Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescr
> iptor.aslc              |   86 ++
> 
> Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescr
> iptor.inf               |   45 +
> 
> Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescr
> iptorPei.c              |   66 +
> 
> Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosUpdateConfig/SystemBiosU
> pdateConfig.ini           |   72 +
> 
> Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosUpdateConfig/SystemBiosU
> pdateConfigGcc.ini        |   72 +
>  Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLib.c
> |  156 +-
>  Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLib.inf
> |    8 +-
>  Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLibDxe.c
> |   62 +
>  Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLibDxe.inf
> |   49 +
>  Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLibDxeRuntimeSmm.c
> |  188 +++
>  Vlv2TbltDevicePkg/Library/FlashDeviceLib/SpiChipDefinitions.h
> |    5 +-
>  Vlv2TbltDevicePkg/Library/PlatformBdsLib/BdsPlatform.c
> |  117 +-
>  Vlv2TbltDevicePkg/Library/PlatformBdsLib/PlatformBdsLib.inf
> |    2 +
>  Vlv2TbltDevicePkg/PlatformCapsule.dsc                                                         |   44 +
>  Vlv2TbltDevicePkg/PlatformCapsule.fdf                                                         |   81 ++
>  Vlv2TbltDevicePkg/PlatformCapsuleGcc.fdf                                                      |   81
> ++
>  Vlv2TbltDevicePkg/PlatformPkg.fdf                                                             |  132 +-
>  Vlv2TbltDevicePkg/PlatformPkgConfig.dsc                                                       |    3 +-
>  Vlv2TbltDevicePkg/PlatformPkgGcc.fdf                                                          |  132 +-
>  Vlv2TbltDevicePkg/PlatformPkgGccX64.dsc                                                       |   70
> +-
>  Vlv2TbltDevicePkg/PlatformPkgIA32.dsc                                                         |   70 +-
>  Vlv2TbltDevicePkg/PlatformPkgX64.dsc                                                          |   70 +-
>  Vlv2TbltDevicePkg/bld_vlv.bat                                                                 |    8 +-
>  124 files changed, 17848 insertions(+), 384 deletions(-)
>  create mode 100644
> MdeModulePkg/Application/CapsuleApp/AppSupport.c
>  create mode 100644 MdeModulePkg/Application/CapsuleApp/CapsuleApp.c
>  create mode 100644
> MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf
>  create mode 100644
> MdeModulePkg/Application/CapsuleApp/CapsuleApp.uni
>  create mode 100644
> MdeModulePkg/Application/CapsuleApp/CapsuleAppExtra.uni
>  create mode 100644
> MdeModulePkg/Application/CapsuleApp/CapsuleDump.c
>  create mode 100644
> MdeModulePkg/Include/Guid/EdkiiSystemFmpCapsule.h
>  create mode 100644
> MdeModulePkg/Include/Library/EdkiiSystemCapsuleLib.h
>  create mode 100644
> MdeModulePkg/Include/Library/FmpAuthenticationLib.h
>  create mode 100644 MdeModulePkg/Include/Library/IniParsingLib.h
>  create mode 100644
> MdeModulePkg/Include/Library/PlatformFlashAccessLib.h
>  create mode 100644
> MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.c
>  create mode 100644
> MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.inf
>  create mode 100644
> MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.uni
>  create mode 100644
> MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleProcessLib.c
>  create mode 100644
> MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleReportLib.c
>  create mode 100644
> MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleRuntime.c
>  create mode 100644
> MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf
>  create mode 100644
> MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.uni
>  create mode 100644
> MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.c
>  create mode 100644
> MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.inf
>  create mode 100644
> MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.uni
>  create mode 100644
> MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.c
>  create mode 100644
> MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.inf
>  create mode 100644
> MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.uni
>  create mode 100644 MdeModulePkg/Library/IniParsingLib/IniParsingLib.c
>  create mode 100644 MdeModulePkg/Library/IniParsingLib/IniParsingLib.inf
>  create mode 100644 MdeModulePkg/Library/IniParsingLib/IniParsingLib.uni
>  create mode 100644
> MdeModulePkg/Library/PlatformFlashAccessLibNull/PlatformFlashAccessLib
> Null.c
>  create mode 100644
> MdeModulePkg/Library/PlatformFlashAccessLibNull/PlatformFlashAccessLib
> Null.inf
>  create mode 100644
> MdeModulePkg/Library/PlatformFlashAccessLibNull/PlatformFlashAccessLib
> Null.uni
>  create mode 100644
> MdeModulePkg/Universal/RecoveryModuleLoadPei/ParseConfigProfile.c
>  create mode 100644
> MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadP
> ei.c
>  create mode 100644
> MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadP
> ei.h
>  create mode 100644
> MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadP
> ei.inf
>  create mode 100644
> MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadP
> ei.uni
>  create mode 100644
> MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadP
> eiExtra.uni
>  create mode 100644
> MdeModulePkg/Universal/SystemBiosUpdate/ParseConfigProfile.c
>  create mode 100644
> MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosDxe.h
>  create mode 100644
> MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosMainDxe.c
>  create mode 100644
> MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosMainSetImage.c
>  create mode 100644
> MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosMainSetImageDu
> mmy.c
>  create mode 100644
> MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxe.inf
>  create mode 100644
> MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxe.uni
>  create mode 100644
> MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxeExtra.u
> ni
>  create mode 100644
> MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxe.inf
>  create mode 100644
> MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxe.uni
>  create mode 100644
> MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxeExtra.
> uni
>  create mode 100644
> QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/Platfor
> mFlashAccessLibDxe.c
>  create mode 100644
> QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/Platfor
> mFlashAccessLibDxe.inf
>  create mode 100644
> QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/SpiFlash
> Device.c
>  create mode 100644
> QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/SpiFlash
> Device.h
>  create mode 100644
> QuarkPlatformPkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescr
> iptor.aslc
>  create mode 100644
> QuarkPlatformPkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescr
> iptor.inf
>  create mode 100644
> QuarkPlatformPkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescr
> iptorPei.c
>  create mode 100644
> QuarkPlatformPkg/Feature/Capsule/SystemBiosUpdateConfig/SystemBiosU
> pdateConfig.ini
>  create mode 100644 QuarkPlatformPkg/QuarkCapsule.dsc
>  create mode 100644 QuarkPlatformPkg/QuarkCapsule.fdf
>  create mode 100644
> SecurityPkg/Library/FmpAuthenticationPkcs7Lib/FmpAuthenticationPkcs7Lib
> .c
>  create mode 100644
> SecurityPkg/Library/FmpAuthenticationPkcs7Lib/FmpAuthenticationPkcs7Lib
> .inf
>  create mode 100644
> SecurityPkg/Library/FmpAuthenticationPkcs7Lib/FmpAuthenticationPkcs7Lib
> .uni
>  create mode 100644
> SecurityPkg/Library/FmpAuthenticationRsa2048Sha256Lib/FmpAuthenticatio
> nRsa2048Sha256Lib.c
>  create mode 100644
> SecurityPkg/Library/FmpAuthenticationRsa2048Sha256Lib/FmpAuthenticatio
> nRsa2048Sha256Lib.inf
>  create mode 100644
> SecurityPkg/Library/FmpAuthenticationRsa2048Sha256Lib/FmpAuthenticatio
> nRsa2048Sha256Lib.uni
>  create mode 100644
> UefiCpuPkg/Application/MicrocodeCapsuleApp/AppSupport.c
>  create mode 100644
> UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.c
>  create mode 100644
> UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.inf
>  create mode 100644
> UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.uni
>  create mode 100644
> UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleAppExtra.
> uni
>  create mode 100644
> UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleDump.c
>  create mode 100644 UefiCpuPkg/Include/Guid/MicrocodeFmp.h
>  create mode 100644
> UefiCpuPkg/Include/Library/MicrocodeFlashAccessLib.h
>  create mode 100644
> UefiCpuPkg/Library/MicrocodeFlashAccessLibNull/MicrocodeFlashAccessLib
> Null.c
>  create mode 100644
> UefiCpuPkg/Library/MicrocodeFlashAccessLibNull/MicrocodeFlashAccessLib
> Null.inf
>  create mode 100644
> UefiCpuPkg/Library/MicrocodeFlashAccessLibNull/MicrocodeFlashAccessLib
> Null.uni
>  create mode 100644 UefiCpuPkg/MicrocodeUpdate/MicrocodeFmp.c
>  create mode 100644 UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.c
>  create mode 100644 UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.h
>  create mode 100644 UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.inf
>  create mode 100644
> UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdateDxe.uni
>  create mode 100644
> UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdateDxeExtra.uni
>  create mode 100644
> Vlv2TbltDevicePkg/Feature/Capsule/Library/PlatformFlashAccessLib/Platfor
> mFlashAccessLib.c
>  create mode 100644
> Vlv2TbltDevicePkg/Feature/Capsule/Library/PlatformFlashAccessLib/Platfor
> mFlashAccessLib.inf
>  create mode 100644
> Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescr
> iptor.aslc
>  create mode 100644
> Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescr
> iptor.inf
>  create mode 100644
> Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescr
> iptorPei.c
>  create mode 100644
> Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosUpdateConfig/SystemBiosU
> pdateConfig.ini
>  create mode 100644
> Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosUpdateConfig/SystemBiosU
> pdateConfigGcc.ini
>  create mode 100644
> Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLibDxe.c
>  create mode 100644
> Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLibDxe.inf
>  create mode 100644
> Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLibDxeRuntimeSmm.c
>  create mode 100644 Vlv2TbltDevicePkg/PlatformCapsule.dsc
>  create mode 100644 Vlv2TbltDevicePkg/PlatformCapsule.fdf
>  create mode 100644 Vlv2TbltDevicePkg/PlatformCapsuleGcc.fdf
> 
> --
> 2.7.4.windows.1
> 
> _______________________________________________
> edk2-devel mailing list
> edk2-devel@lists.01.org
> https://lists.01.org/mailman/listinfo/edk2-devel


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

* Re: [PATCH 27/45] UefiCpuPkg/MicrocodeUpdate: Add MicrocodeUpdate component.
  2016-09-21  6:45 ` [PATCH 27/45] UefiCpuPkg/MicrocodeUpdate: Add MicrocodeUpdate component Jiewen Yao
@ 2016-09-27  8:41   ` Fan, Jeff
  0 siblings, 0 replies; 83+ messages in thread
From: Fan, Jeff @ 2016-09-27  8:41 UTC (permalink / raw)
  To: Yao, Jiewen, edk2-devel@lists.01.org
  Cc: Tian, Feng, Zeng, Star, Kinney, Michael D, Gao, Liming,
	Zhang, Chao B

Jiewen,

1.  Could you move structure definitions (like MICROCODE_FMP_LAST_ATTEMPT_VARIABLE, etc ) and function declarations reference (like GetMicrocodeInfo, etc) from MicrocodeFmp.c to MicrocodeUpdate.h?
2.  Correct EFI_D_ERROR to EFI_D_INFO on following DEBUG ().
       DEBUG((EFI_D_ERROR, "Microcode Region - 0x%lx - 0x%lx\n", MicrocodePatchAddress, MicrocodePatchRegionSize));

The others part on UefiCpuPkg are good to me!

Reviewed-by: Jeff Fan <jeff.fan@intel.com>

Jeff

-----Original Message-----
From: Yao, Jiewen 
Sent: Wednesday, September 21, 2016 2:45 PM
To: edk2-devel@lists.01.org
Cc: Fan, Jeff; Tian, Feng; Zeng, Star; Kinney, Michael D; Gao, Liming; Zhang, Chao B
Subject: [PATCH 27/45] UefiCpuPkg/MicrocodeUpdate: Add MicrocodeUpdate component.

MicrocodeUpdate supports update Microcode region via UEFI FMP capsule.

MicrocodeUpdate SetImage() will perform the Microcode version,
ProcessorSignature/ProcessorFlag, and try to load microcode.
If and only if the Microcode is loaded successfully, and new Microcode
will be updated to system flash region.

Cc: Jeff Fan <jeff.fan@intel.com>
Cc: Feng Tian <feng.tian@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Chao Zhang <chao.b.zhang@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
---
 UefiCpuPkg/MicrocodeUpdate/MicrocodeFmp.c              | 641 ++++++++++++++++
 UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.c           | 775 ++++++++++++++++++++
 UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.h           | 299 ++++++++
 UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.inf         |  68 ++
 UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdateDxe.uni      |  21 +
 UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdateDxeExtra.uni |  20 +
 6 files changed, 1824 insertions(+)

diff --git a/UefiCpuPkg/MicrocodeUpdate/MicrocodeFmp.c b/UefiCpuPkg/MicrocodeUpdate/MicrocodeFmp.c
new file mode 100644
index 0000000..ee94b41
--- /dev/null
+++ b/UefiCpuPkg/MicrocodeUpdate/MicrocodeFmp.c
@@ -0,0 +1,641 @@
+/** @file
+  Produce FMP instance for Microcode.
+
+  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "MicrocodeUpdate.h"
+
+#define MICROCODE_FMP_PRIVATE_DATA_SIGNATURE  SIGNATURE_32('M', 'C', 'U', 'F')
+
+//
+// Microcode FMP private data structure.
+//
+
+typedef struct {
+  UINT32 LastAttemptVersion;
+  UINT32 LastAttemptStatus;
+} MICROCODE_FMP_LAST_ATTEMPT_VARIABLE;
+
+struct _MICROCODE_FMP_PRIVATE_DATA {
+  UINT32                               Signature;
+  EFI_FIRMWARE_MANAGEMENT_PROTOCOL     Fmp;
+  EFI_HANDLE                           Handle;
+  UINT8                                DescriptorCount;
+  EFI_FIRMWARE_IMAGE_DESCRIPTOR        *ImageDescriptor;
+  UINT32                               PackageVersion;
+  CHAR16                               *PackageVersionName;
+  MICROCODE_FMP_LAST_ATTEMPT_VARIABLE  LastAttempt;
+};
+
+typedef struct _MICROCODE_FMP_PRIVATE_DATA  MICROCODE_FMP_PRIVATE_DATA;
+
+#define MICROCODE_FMP_LAST_ATTEMPT_VARIABLE_NAME  L"MicrocodeLastAttempVar"
+
+/**
+  Returns a pointer to the MICROCODE_FMP_PRIVATE_DATA structure from the input a as Fmp.
+
+  If the signatures matches, then a pointer to the data structure that contains
+  a specified field of that data structure is returned.
+
+  @param  a              Pointer to the field specified by ServiceBinding within
+                         a data structure of type MICROCODE_FMP_PRIVATE_DATA.
+
+**/
+#define MICROCODE_FMP_PRIVATE_DATA_FROM_FMP(a) \
+  CR ( \
+  (a), \
+  MICROCODE_FMP_PRIVATE_DATA, \
+  Fmp, \
+  MICROCODE_FMP_PRIVATE_DATA_SIGNATURE \
+  )
+
+//
+// MicrocodeFmp driver private data
+//
+MICROCODE_FMP_PRIVATE_DATA *mMicrocodeFmpPrivate = NULL;
+
+EFI_FIRMWARE_MANAGEMENT_PROTOCOL mFirmwareManagementProtocol = {
+  FmpGetImageInfo,
+  FmpGetImage,
+  FmpSetImage,
+  FmpCheckImage,
+  FmpGetPackageInfo,
+  FmpSetPackageInfo
+};
+
+/**
+  Get current Microcode information.
+
+  @param[out]  ImageDescriptor  Microcode ImageDescriptor
+  @param[in]   DescriptorCount  The count of Microcode ImageDescriptor allocated.
+
+  @return Microcode count
+**/
+UINTN
+GetMicrocodeInfo(
+  OUT EFI_FIRMWARE_IMAGE_DESCRIPTOR  *ImageDescriptor, OPTIONAL
+  IN  UINTN                          DescriptorCount   OPTIONAL
+  );
+
+/**
+  Read Microcode.
+
+  @param  ImageIndex The index of Microcode image.
+  @param  Image      The Microcode image buffer.
+  @param  ImageSize  The size of Microcode image buffer in bytes.
+
+  @retval EFI_SUCCESS    The Microcode image is read.
+  @retval EFI_NOT_FOUND  The Microcode image is not found.
+**/
+EFI_STATUS
+MicrocodeRead(
+  IN UINTN      ImageIndex,
+  IN OUT VOID   *Image,
+  IN OUT UINTN  *ImageSize
+  );
+
+/**
+  Write Microcode.
+
+  @param  ImageIndex         The index of Microcode image.
+  @param  Image              The Microcode image buffer.
+  @param  ImageSize          The size of Microcode image buffer in bytes.
+  @param  LastAttemptVersion The last attempt version, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+  @param  LastAttemptStatus  The last attempt status, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+  @param  AbortReason        A pointer to a pointer to a null-terminated string providing more
+                             details for the aborted operation. The buffer is allocated by this function
+                             with AllocatePool(), and it is the caller's responsibility to free it with a
+                             call to FreePool().
+
+  @retval EFI_SUCCESS               The Microcode image is written.
+  @retval EFI_VOLUME_CORRUPTED      The Microcode image is corrupt.
+  @retval EFI_INCOMPATIBLE_VERSION  The Microcode image version is incorrect.
+  @retval EFI_SECURITY_VIOLATION    The Microcode image fails to load.
+  @retval EFI_WRITE_PROTECTED   The flash device is read only.
+**/
+EFI_STATUS
+MicrocodeWrite(
+  IN UINTN   ImageIndex,
+  IN VOID    *Image,
+  IN UINTN   ImageSize,
+  OUT UINT32 *LastAttemptVersion,
+  OUT UINT32 *LastAttemptStatus,
+  OUT CHAR16 **AbortReason
+  );
+
+/**
+  Initialize Microcode Descriptor.
+
+  @param MicrocodeFmpPrivate private data structure to be initialized.
+
+  @return EFI_SUCCESS Microcode Descriptor is initialized.
+**/
+EFI_STATUS
+InitializeMicrocodeDescriptor(
+  IN MICROCODE_FMP_PRIVATE_DATA *MicrocodeFmpPrivate
+  );
+
+/**
+  Returns information about the current firmware image(s) of the device.
+
+  This function allows a copy of the current firmware image to be created and saved.
+  The saved copy could later been used, for example, in firmware image recovery or rollback.
+
+  @param[in]      This               A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
+  @param[in, out] ImageInfoSize      A pointer to the size, in bytes, of the ImageInfo buffer.
+                                     On input, this is the size of the buffer allocated by the caller.
+                                     On output, it is the size of the buffer returned by the firmware
+                                     if the buffer was large enough, or the size of the buffer needed
+                                     to contain the image(s) information if the buffer was too small.
+  @param[in, out] ImageInfo          A pointer to the buffer in which firmware places the current image(s)
+                                     information. The information is an array of EFI_FIRMWARE_IMAGE_DESCRIPTORs.
+  @param[out]     DescriptorVersion  A pointer to the location in which firmware returns the version number
+                                     associated with the EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+  @param[out]     DescriptorCount    A pointer to the location in which firmware returns the number of
+                                     descriptors or firmware images within this device.
+  @param[out]     DescriptorSize     A pointer to the location in which firmware returns the size, in bytes,
+                                     of an individual EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+  @param[out]     PackageVersion     A version number that represents all the firmware images in the device.
+                                     The format is vendor specific and new version must have a greater value
+                                     than the old version. If PackageVersion is not supported, the value is
+                                     0xFFFFFFFF. A value of 0xFFFFFFFE indicates that package version comparison
+                                     is to be performed using PackageVersionName. A value of 0xFFFFFFFD indicates
+                                     that package version update is in progress.
+  @param[out]     PackageVersionName A pointer to a pointer to a null-terminated string representing the
+                                     package version name. The buffer is allocated by this function with
+                                     AllocatePool(), and it is the caller's responsibility to free it with a call
+                                     to FreePool().
+
+  @retval EFI_SUCCESS                The device was successfully updated with the new image.
+  @retval EFI_BUFFER_TOO_SMALL       The ImageInfo buffer was too small. The current buffer size
+                                     needed to hold the image(s) information is returned in ImageInfoSize.
+  @retval EFI_INVALID_PARAMETER      ImageInfoSize is NULL.
+  @retval EFI_DEVICE_ERROR           Valid information could not be returned. Possible corrupted image.
+
+**/
+EFI_STATUS
+EFIAPI
+FmpGetImageInfo (
+  IN        EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This,
+  IN OUT    UINTN                            *ImageInfoSize,
+  IN OUT    EFI_FIRMWARE_IMAGE_DESCRIPTOR    *ImageInfo,
+  OUT       UINT32                           *DescriptorVersion,
+  OUT       UINT8                            *DescriptorCount,
+  OUT       UINTN                            *DescriptorSize,
+  OUT       UINT32                           *PackageVersion,
+  OUT       CHAR16                           **PackageVersionName
+  )
+{
+  MICROCODE_FMP_PRIVATE_DATA *MicrocodeFmpPrivate;
+  UINTN                      Index;
+
+  MicrocodeFmpPrivate = MICROCODE_FMP_PRIVATE_DATA_FROM_FMP(This);
+
+  if(ImageInfoSize == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (*ImageInfoSize < sizeof(EFI_FIRMWARE_IMAGE_DESCRIPTOR) * MicrocodeFmpPrivate->DescriptorCount) {
+    *ImageInfoSize = sizeof(EFI_FIRMWARE_IMAGE_DESCRIPTOR) * MicrocodeFmpPrivate->DescriptorCount;
+    return EFI_BUFFER_TOO_SMALL;
+  }
+
+  if (ImageInfo == NULL ||
+      DescriptorVersion == NULL ||
+      DescriptorCount == NULL ||
+      DescriptorSize == NULL ||
+      PackageVersion == NULL ||
+      PackageVersionName == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  *ImageInfoSize      = sizeof(EFI_FIRMWARE_IMAGE_DESCRIPTOR) * MicrocodeFmpPrivate->DescriptorCount;
+  *DescriptorSize     = sizeof(EFI_FIRMWARE_IMAGE_DESCRIPTOR);
+  *DescriptorCount    = MicrocodeFmpPrivate->DescriptorCount;
+  *DescriptorVersion  = EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION;
+
+  //
+  // supports 1 ImageInfo descriptor
+  //
+  CopyMem(&ImageInfo[0], MicrocodeFmpPrivate->ImageDescriptor, sizeof(EFI_FIRMWARE_IMAGE_DESCRIPTOR) * MicrocodeFmpPrivate->DescriptorCount);
+  for (Index = 0; Index < MicrocodeFmpPrivate->DescriptorCount; Index++) {
+    if ((ImageInfo[Index].AttributesSetting & IMAGE_ATTRIBUTE_IN_USE) != 0) {
+      ImageInfo[Index].LastAttemptVersion = MicrocodeFmpPrivate->LastAttempt.LastAttemptVersion;
+      ImageInfo[Index].LastAttemptStatus = MicrocodeFmpPrivate->LastAttempt.LastAttemptStatus;
+    }
+  }
+
+  //
+  // package version
+  //
+  *PackageVersion = MicrocodeFmpPrivate->PackageVersion;
+  if (MicrocodeFmpPrivate->PackageVersionName != NULL) {
+    *PackageVersionName = AllocateCopyPool(StrSize(MicrocodeFmpPrivate->PackageVersionName), MicrocodeFmpPrivate->PackageVersionName);
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Retrieves a copy of the current firmware image of the device.
+
+  This function allows a copy of the current firmware image to be created and saved.
+  The saved copy could later been used, for example, in firmware image recovery or rollback.
+
+  @param[in]     This            A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
+  @param[in]     ImageIndex      A unique number identifying the firmware image(s) within the device.
+                                 The number is between 1 and DescriptorCount.
+  @param[in,out] Image           Points to the buffer where the current image is copied to.
+  @param[in,out] ImageSize       On entry, points to the size of the buffer pointed to by Image, in bytes.
+                                 On return, points to the length of the image, in bytes.
+
+  @retval EFI_SUCCESS            The device was successfully updated with the new image.
+  @retval EFI_BUFFER_TOO_SMALL   The buffer specified by ImageSize is too small to hold the
+                                 image. The current buffer size needed to hold the image is returned
+                                 in ImageSize.
+  @retval EFI_INVALID_PARAMETER  The Image was NULL.
+  @retval EFI_NOT_FOUND          The current image is not copied to the buffer.
+  @retval EFI_UNSUPPORTED        The operation is not supported.
+  @retval EFI_SECURITY_VIOLATIO  The operation could not be performed due to an authentication failure.
+
+**/
+EFI_STATUS
+EFIAPI
+FmpGetImage(
+  IN  EFI_FIRMWARE_MANAGEMENT_PROTOCOL  *This,
+  IN  UINT8                             ImageIndex,
+  IN  OUT  VOID                         *Image,
+  IN  OUT  UINTN                        *ImageSize
+  )
+{
+  MICROCODE_FMP_PRIVATE_DATA *MicrocodeFmpPrivate;
+  EFI_STATUS                 Status;
+
+  if (Image == NULL || ImageSize == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  MicrocodeFmpPrivate = MICROCODE_FMP_PRIVATE_DATA_FROM_FMP(This);
+
+  if (ImageIndex == 0 || ImageIndex > MicrocodeFmpPrivate->DescriptorCount || ImageSize == NULL || Image == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Status = MicrocodeRead(ImageIndex, (VOID *)Image, ImageSize);
+  return Status;
+}
+
+/**
+  Updates the firmware image of the device.
+
+  This function updates the hardware with the new firmware image.
+  This function returns EFI_UNSUPPORTED if the firmware image is not updatable.
+  If the firmware image is updatable, the function should perform the following minimal validations
+  before proceeding to do the firmware image update.
+  - Validate the image authentication if image has attribute
+    IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED. The function returns
+    EFI_SECURITY_VIOLATION if the validation fails.
+  - Validate the image is a supported image for this device. The function returns EFI_ABORTED if
+    the image is unsupported. The function can optionally provide more detailed information on
+    why the image is not a supported image.
+  - Validate the data from VendorCode if not null. Image validation must be performed before
+    VendorCode data validation. VendorCode data is ignored or considered invalid if image
+    validation failed. The function returns EFI_ABORTED if the data is invalid.
+
+  VendorCode enables vendor to implement vendor-specific firmware image update policy. Null if
+  the caller did not specify the policy or use the default policy. As an example, vendor can implement
+  a policy to allow an option to force a firmware image update when the abort reason is due to the new
+  firmware image version is older than the current firmware image version or bad image checksum.
+  Sensitive operations such as those wiping the entire firmware image and render the device to be
+  non-functional should be encoded in the image itself rather than passed with the VendorCode.
+  AbortReason enables vendor to have the option to provide a more detailed description of the abort
+  reason to the caller.
+
+  @param[in]  This               A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
+  @param[in]  ImageIndex         A unique number identifying the firmware image(s) within the device.
+                                 The number is between 1 and DescriptorCount.
+  @param[in]  Image              Points to the new image.
+  @param[in]  ImageSize          Size of the new image in bytes.
+  @param[in]  VendorCode         This enables vendor to implement vendor-specific firmware image update policy.
+                                 Null indicates the caller did not specify the policy or use the default policy.
+  @param[in]  Progress           A function used by the driver to report the progress of the firmware update.
+  @param[out] AbortReason        A pointer to a pointer to a null-terminated string providing more
+                                 details for the aborted operation. The buffer is allocated by this function
+                                 with AllocatePool(), and it is the caller's responsibility to free it with a
+                                 call to FreePool().
+
+  @retval EFI_SUCCESS            The device was successfully updated with the new image.
+  @retval EFI_ABORTED            The operation is aborted.
+  @retval EFI_INVALID_PARAMETER  The Image was NULL.
+  @retval EFI_UNSUPPORTED        The operation is not supported.
+  @retval EFI_SECURITY_VIOLATIO  The operation could not be performed due to an authentication failure.
+
+**/
+EFI_STATUS
+EFIAPI
+FmpSetImage(
+  IN  EFI_FIRMWARE_MANAGEMENT_PROTOCOL                 *This,
+  IN  UINT8                                            ImageIndex,
+  IN  CONST VOID                                       *Image,
+  IN  UINTN                                            ImageSize,
+  IN  CONST VOID                                       *VendorCode,
+  IN  EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS    Progress,
+  OUT CHAR16                                           **AbortReason
+  )
+{
+  EFI_STATUS                 Status;
+  EFI_STATUS                 VarStatus;
+  MICROCODE_FMP_PRIVATE_DATA *MicrocodeFmpPrivate;
+
+  if (Image == NULL || AbortReason == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  MicrocodeFmpPrivate = MICROCODE_FMP_PRIVATE_DATA_FROM_FMP(This);
+  *AbortReason     = NULL;
+
+  if (ImageIndex == 0 || ImageIndex > MicrocodeFmpPrivate->DescriptorCount || Image == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Status = MicrocodeWrite(ImageIndex, (VOID *)Image, ImageSize, &MicrocodeFmpPrivate->LastAttempt.LastAttemptVersion, &MicrocodeFmpPrivate->LastAttempt.LastAttemptStatus, AbortReason);
+  DEBUG((EFI_D_INFO, "SetImage - LastAttemp Version - 0x%x, State - 0x%x\n", MicrocodeFmpPrivate->LastAttempt.LastAttemptVersion, MicrocodeFmpPrivate->LastAttempt.LastAttemptStatus));
+  VarStatus = gRT->SetVariable(
+                     MICROCODE_FMP_LAST_ATTEMPT_VARIABLE_NAME,
+                     &gEfiCallerIdGuid,
+                     EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
+                     sizeof(MicrocodeFmpPrivate->LastAttempt),
+                     &MicrocodeFmpPrivate->LastAttempt
+                     );
+  DEBUG((EFI_D_INFO, "SetLastAttemp - %r\n", VarStatus));
+
+  if (!EFI_ERROR(Status)) {
+    InitializeMicrocodeDescriptor(MicrocodeFmpPrivate);
+  }
+
+  return Status;
+}
+
+/**
+  Checks if the firmware image is valid for the device.
+
+  This function allows firmware update application to validate the firmware image without
+  invoking the SetImage() first.
+
+  @param[in]  This               A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
+  @param[in]  ImageIndex         A unique number identifying the firmware image(s) within the device.
+                                 The number is between 1 and DescriptorCount.
+  @param[in]  Image              Points to the new image.
+  @param[in]  ImageSize          Size of the new image in bytes.
+  @param[out] ImageUpdatable     Indicates if the new image is valid for update. It also provides,
+                                 if available, additional information if the image is invalid.
+
+  @retval EFI_SUCCESS            The image was successfully checked.
+  @retval EFI_INVALID_PARAMETER  The Image was NULL.
+  @retval EFI_UNSUPPORTED        The operation is not supported.
+  @retval EFI_SECURITY_VIOLATIO  The operation could not be performed due to an authentication failure.
+
+**/
+EFI_STATUS
+EFIAPI
+FmpCheckImage(
+  IN  EFI_FIRMWARE_MANAGEMENT_PROTOCOL  *This,
+  IN  UINT8                             ImageIndex,
+  IN  CONST VOID                        *Image,
+  IN  UINTN                             ImageSize,
+  OUT UINT32                            *ImageUpdatable
+  )
+{
+  return EFI_UNSUPPORTED;
+}
+
+/**
+  Returns information about the firmware package.
+
+  This function returns package information.
+
+  @param[in]  This                     A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
+  @param[out] PackageVersion           A version number that represents all the firmware images in the device.
+                                       The format is vendor specific and new version must have a greater value
+                                       than the old version. If PackageVersion is not supported, the value is
+                                       0xFFFFFFFF. A value of 0xFFFFFFFE indicates that package version
+                                       comparison is to be performed using PackageVersionName. A value of
+                                       0xFFFFFFFD indicates that package version update is in progress.
+  @param[out] PackageVersionName       A pointer to a pointer to a null-terminated string representing
+                                       the package version name. The buffer is allocated by this function with
+                                       AllocatePool(), and it is the caller's responsibility to free it with a
+                                       call to FreePool().
+  @param[out] PackageVersionNameMaxLen The maximum length of package version name if device supports update of
+                                       package version name. A value of 0 indicates the device does not support
+                                       update of package version name. Length is the number of Unicode characters,
+                                       including the terminating null character.
+  @param[out] AttributesSupported      Package attributes that are supported by this device. See 'Package Attribute
+                                       Definitions' for possible returned values of this parameter. A value of 1
+                                       indicates the attribute is supported and the current setting value is
+                                       indicated in AttributesSetting. A value of 0 indicates the attribute is not
+                                       supported and the current setting value in AttributesSetting is meaningless.
+  @param[out] AttributesSetting        Package attributes. See 'Package Attribute Definitions' for possible returned
+                                       values of this parameter
+
+  @retval EFI_SUCCESS                  The package information was successfully returned.
+  @retval EFI_UNSUPPORTED              The operation is not supported.
+
+**/
+EFI_STATUS
+EFIAPI
+FmpGetPackageInfo(
+  IN  EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This,
+  OUT UINT32                           *PackageVersion,
+  OUT CHAR16                           **PackageVersionName,
+  OUT UINT32                           *PackageVersionNameMaxLen,
+  OUT UINT64                           *AttributesSupported,
+  OUT UINT64                           *AttributesSetting
+  )
+{
+  return EFI_UNSUPPORTED;
+}
+
+/**
+  Updates information about the firmware package.
+
+  This function updates package information.
+  This function returns EFI_UNSUPPORTED if the package information is not updatable.
+  VendorCode enables vendor to implement vendor-specific package information update policy.
+  Null if the caller did not specify this policy or use the default policy.
+
+  @param[in]  This               A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
+  @param[in]  Image              Points to the authentication image.
+                                 Null if authentication is not required.
+  @param[in]  ImageSize          Size of the authentication image in bytes.
+                                 0 if authentication is not required.
+  @param[in]  VendorCode         This enables vendor to implement vendor-specific firmware
+                                 image update policy.
+                                 Null indicates the caller did not specify this policy or use
+                                 the default policy.
+  @param[in]  PackageVersion     The new package version.
+  @param[in]  PackageVersionName A pointer to the new null-terminated Unicode string representing
+                                 the package version name.
+                                 The string length is equal to or less than the value returned in
+                                 PackageVersionNameMaxLen.
+
+  @retval EFI_SUCCESS            The device was successfully updated with the new package
+                                 information.
+  @retval EFI_INVALID_PARAMETER  The PackageVersionName length is longer than the value
+                                 returned in PackageVersionNameMaxLen.
+  @retval EFI_UNSUPPORTED        The operation is not supported.
+  @retval EFI_SECURITY_VIOLATIO  The operation could not be performed due to an authentication failure.
+
+**/
+EFI_STATUS
+EFIAPI
+FmpSetPackageInfo(
+  IN  EFI_FIRMWARE_MANAGEMENT_PROTOCOL   *This,
+  IN  CONST VOID                         *Image,
+  IN  UINTN                              ImageSize,
+  IN  CONST VOID                         *VendorCode,
+  IN  UINT32                             PackageVersion,
+  IN  CONST CHAR16                       *PackageVersionName
+  )
+{
+  return EFI_UNSUPPORTED;
+}
+
+/**
+  Initialize Microcode Descriptor.
+
+  @param MicrocodeFmpPrivate private data structure to be initialized.
+
+  @return EFI_SUCCESS Microcode Descriptor is initialized.
+**/
+EFI_STATUS
+InitializeMicrocodeDescriptor (
+  IN MICROCODE_FMP_PRIVATE_DATA *MicrocodeFmpPrivate
+  )
+{
+  UINT8  CurrentMicrocodeCount;
+
+  CurrentMicrocodeCount = (UINT8)GetMicrocodeInfo(NULL, 0);
+
+  if (CurrentMicrocodeCount > MicrocodeFmpPrivate->DescriptorCount) {
+    if (MicrocodeFmpPrivate->ImageDescriptor != NULL) {
+      FreePool(MicrocodeFmpPrivate->ImageDescriptor);
+      MicrocodeFmpPrivate->ImageDescriptor = NULL;
+    }
+  } else {
+    ZeroMem(MicrocodeFmpPrivate->ImageDescriptor, MicrocodeFmpPrivate->DescriptorCount * sizeof(EFI_FIRMWARE_IMAGE_DESCRIPTOR));
+  }
+
+  MicrocodeFmpPrivate->DescriptorCount = CurrentMicrocodeCount;
+
+  if (MicrocodeFmpPrivate->ImageDescriptor == NULL) {
+    MicrocodeFmpPrivate->ImageDescriptor = AllocateZeroPool(MicrocodeFmpPrivate->DescriptorCount * sizeof(EFI_FIRMWARE_IMAGE_DESCRIPTOR));
+    if (MicrocodeFmpPrivate->ImageDescriptor == NULL) {
+      return EFI_OUT_OF_RESOURCES;
+    }
+  }
+
+  CurrentMicrocodeCount = (UINT8)GetMicrocodeInfo(MicrocodeFmpPrivate->ImageDescriptor, MicrocodeFmpPrivate->DescriptorCount);
+  ASSERT(CurrentMicrocodeCount == MicrocodeFmpPrivate->DescriptorCount);
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Initialize MicrocodeFmpDriver private data structure.
+
+  @param MicrocodeFmpPrivate private data structure to be initialized.
+
+  @return EFI_SUCCESS private data is initialized.
+**/
+EFI_STATUS
+InitializePrivateData(
+  IN MICROCODE_FMP_PRIVATE_DATA *MicrocodeFmpPrivate
+  )
+{
+  EFI_STATUS       Status;
+  EFI_STATUS       VarStatus;
+  UINTN            VarSize;
+
+  MicrocodeFmpPrivate->Signature       = MICROCODE_FMP_PRIVATE_DATA_SIGNATURE;
+  MicrocodeFmpPrivate->Handle          = NULL;
+  CopyMem(&MicrocodeFmpPrivate->Fmp, &mFirmwareManagementProtocol, sizeof(EFI_FIRMWARE_MANAGEMENT_PROTOCOL));
+
+  MicrocodeFmpPrivate->PackageVersion = 0x1;
+  MicrocodeFmpPrivate->PackageVersionName = L"Microcode";
+
+  MicrocodeFmpPrivate->LastAttempt.LastAttemptVersion = 0x0;
+  MicrocodeFmpPrivate->LastAttempt.LastAttemptStatus = 0x0;
+  VarSize = sizeof(MicrocodeFmpPrivate->LastAttempt);
+  VarStatus = gRT->GetVariable(
+                     MICROCODE_FMP_LAST_ATTEMPT_VARIABLE_NAME,
+                     &gEfiCallerIdGuid,
+                     NULL,
+                     &VarSize,
+                     &MicrocodeFmpPrivate->LastAttempt
+                     );
+  DEBUG((EFI_D_INFO, "GetLastAttemp - %r\n", VarStatus));
+  DEBUG((EFI_D_INFO, "GetLastAttemp Version - 0x%x, State - 0x%x\n", MicrocodeFmpPrivate->LastAttempt.LastAttemptVersion, MicrocodeFmpPrivate->LastAttempt.LastAttemptStatus));
+
+  Status = InitializeMicrocodeDescriptor(MicrocodeFmpPrivate);
+
+  return Status;
+}
+
+/**
+  Microcode FMP module entrypoint
+
+  @param  ImageHandle       The firmware allocated handle for the EFI image.
+  @param  SystemTable       A pointer to the EFI System Table.
+
+  @return EFI_SUCCESS Microcode FMP module is initialized.
+**/
+EFI_STATUS
+EFIAPI
+MicrocodeFmpMain (
+  IN EFI_HANDLE                         ImageHandle,
+  IN EFI_SYSTEM_TABLE                   *SystemTable
+  )
+{
+  EFI_STATUS                            Status;
+
+  //
+  // Initialize MicrocodeFmpPrivateData
+  //
+  mMicrocodeFmpPrivate = AllocateZeroPool (sizeof(MICROCODE_FMP_PRIVATE_DATA));
+  if (mMicrocodeFmpPrivate == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  Status = InitializePrivateData(mMicrocodeFmpPrivate);
+  if (EFI_ERROR(Status)) {
+    FreePool(mMicrocodeFmpPrivate);
+    mMicrocodeFmpPrivate = NULL;
+    return Status;
+  }
+
+  //
+  // Install FMP protocol.
+  //
+  Status = gBS->InstallProtocolInterface (
+                  &mMicrocodeFmpPrivate->Handle,
+                  &gEfiFirmwareManagementProtocolGuid,
+                  EFI_NATIVE_INTERFACE,
+                  &mMicrocodeFmpPrivate->Fmp
+                  );
+  if (EFI_ERROR (Status)) {
+    FreePool(mMicrocodeFmpPrivate);
+    mMicrocodeFmpPrivate = NULL;
+    return Status;
+  }
+
+  return Status;
+}
diff --git a/UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.c b/UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.c
new file mode 100644
index 0000000..d19eca9
--- /dev/null
+++ b/UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.c
@@ -0,0 +1,775 @@
+/** @file
+  SetImage instance to update Microcode.
+
+  Caution: This module requires additional review when modified.
+  This module will have external input - capsule image.
+  This external input must be validated carefully to avoid security issue like
+  buffer overflow, integer overflow.
+
+  MicrocodeWrite() and VerifyMicrocode() will receive untrusted input and do basic validation.
+
+  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "MicrocodeUpdate.h"
+
+/**
+  Get Microcode Region.
+
+  @param[out] MicrocodePatchAddress      The address of Microcode
+  @param[out] MicrocodePatchRegionSize   The region size of Microcode
+
+  @retval TRUE   The Microcode region is returned.
+  @retval FALSE  No Microcode region.
+**/
+BOOLEAN
+GetMicrocodeRegion(
+  OUT UINT64   *MicrocodePatchAddress,
+  OUT UINT64   *MicrocodePatchRegionSize
+  )
+{
+  *MicrocodePatchAddress = PcdGet64(PcdCpuMicrocodePatchAddress);
+  *MicrocodePatchRegionSize = PcdGet64(PcdCpuMicrocodePatchRegionSize);
+
+  if ((*MicrocodePatchAddress == 0) || (*MicrocodePatchRegionSize == 0)) {
+    return FALSE;
+  }
+
+  return TRUE;
+}
+
+/**
+  Get Microcode update signature of currently loaded Microcode update.
+
+  @return  Microcode signature.
+
+**/
+UINT32
+GetCurrentMicrocodeSignature(
+  VOID
+  )
+{
+  UINT64 Signature;
+
+  AsmWriteMsr64(MSR_IA32_BIOS_SIGN_ID, 0);
+  AsmCpuid(CPUID_VERSION_INFO, NULL, NULL, NULL, NULL);
+  Signature = AsmReadMsr64(MSR_IA32_BIOS_SIGN_ID);
+  return (UINT32)RShiftU64(Signature, 32);
+}
+
+/**
+  Get current processor signature.
+
+  @return current processor signature.
+**/
+UINT32
+GetCurrentProcessorSignature(
+  VOID
+  )
+{
+  UINT32                                  RegEax;
+  AsmCpuid(CPUID_VERSION_INFO, &RegEax, NULL, NULL, NULL);
+  return RegEax;
+}
+
+/**
+  Get current platform ID.
+
+  @return current platform ID.
+**/
+UINT8
+GetCurrentPlatformId(
+  VOID
+  )
+{
+  UINT8                                   PlatformId;
+
+  PlatformId = (UINT8)AsmMsrBitFieldRead64(MSR_IA32_PLATFORM_ID, 50, 52);
+  return PlatformId;
+}
+
+/**
+  Load new Microcode.
+
+  @param Address  The address of new Microcode.
+
+  @return  Loaded Microcode signature.
+
+**/
+UINT32
+LoadMicrocode(
+  IN UINT64  Address
+  )
+{
+  AsmWriteMsr64(MSR_IA32_BIOS_UPDT_TRIG, Address);
+  return GetCurrentMicrocodeSignature();
+}
+
+/**
+  Get current Microcode information.
+
+  @param[out]  ImageDescriptor  Microcode ImageDescriptor
+  @param[in]   DescriptorCount  The count of Microcode ImageDescriptor allocated.
+
+  @return Microcode count
+**/
+UINTN
+GetMicrocodeInfo(
+  OUT EFI_FIRMWARE_IMAGE_DESCRIPTOR  *ImageDescriptor, OPTIONAL
+  IN  UINTN                          DescriptorCount   OPTIONAL
+  )
+{
+  BOOLEAN                                 Result;
+  UINT64                                  MicrocodePatchAddress;
+  UINT64                                  MicrocodePatchRegionSize;
+  CPU_MICROCODE_HEADER                    *MicrocodeEntryPoint;
+  UINTN                                   MicrocodeEnd;
+  UINTN                                   TotalSize;
+  UINTN                                   Count;
+  UINT64                                  ImageAttributes;
+  UINT32                                  CurrentRevision;
+
+  Result = GetMicrocodeRegion(&MicrocodePatchAddress, &MicrocodePatchRegionSize);
+  if (!Result) {
+    DEBUG((EFI_D_ERROR, "Fail to get Microcode Region\n"));
+    return 0;
+  }
+  DEBUG((EFI_D_ERROR, "Microcode Region - 0x%lx - 0x%lx\n", MicrocodePatchAddress, MicrocodePatchRegionSize));
+
+  Count = 0;
+  CurrentRevision = GetCurrentMicrocodeSignature();
+
+  MicrocodeEnd = (UINTN)(MicrocodePatchAddress + MicrocodePatchRegionSize);
+  MicrocodeEntryPoint = (CPU_MICROCODE_HEADER *) (UINTN) MicrocodePatchAddress;
+  do {
+    if (MicrocodeEntryPoint->HeaderVersion == 0x1 && MicrocodeEntryPoint->LoaderRevision == 0x1) {
+      //
+      // It is the microcode header. It is not the padding data between microcode patches
+      // becasue the padding data should not include 0x00000001 and it should be the repeated
+      // byte format (like 0xXYXYXYXY....).
+      //
+      if (MicrocodeEntryPoint->DataSize == 0) {
+        TotalSize = 2048;
+      } else {
+        TotalSize = MicrocodeEntryPoint->TotalSize;
+      }
+
+      if (ImageDescriptor != NULL && DescriptorCount > Count) {
+        ImageDescriptor[Count].ImageIndex = (UINT8)(Count + 1);
+        CopyGuid (&ImageDescriptor[Count].ImageTypeId, &gMicrocodeFmpImageTypeIdGuid);
+        ImageDescriptor[Count].ImageId = LShiftU64(MicrocodeEntryPoint->ProcessorFlags, 32) + MicrocodeEntryPoint->ProcessorSignature.Uint32;
+        ImageDescriptor[Count].ImageIdName = NULL;
+        ImageDescriptor[Count].Version = MicrocodeEntryPoint->UpdateRevision;
+        ImageDescriptor[Count].VersionName = NULL;
+        ImageDescriptor[Count].Size = TotalSize;
+        ImageAttributes = IMAGE_ATTRIBUTE_IMAGE_UPDATABLE | IMAGE_ATTRIBUTE_RESET_REQUIRED;
+        if (CurrentRevision == MicrocodeEntryPoint->UpdateRevision) {
+          ImageAttributes |= IMAGE_ATTRIBUTE_IN_USE;
+        }
+        ImageDescriptor[Count].AttributesSupported = ImageAttributes | IMAGE_ATTRIBUTE_IN_USE;
+        ImageDescriptor[Count].AttributesSetting = ImageAttributes;
+        ImageDescriptor[Count].Compatibilities = 0;
+        ImageDescriptor[Count].LowestSupportedImageVersion = MicrocodeEntryPoint->UpdateRevision; // do not support rollback
+        ImageDescriptor[Count].LastAttemptVersion = 0;
+        ImageDescriptor[Count].LastAttemptStatus = 0;
+        ImageDescriptor[Count].HardwareInstance = 0;
+      }
+    } else {
+      //
+      // It is the padding data between the microcode patches for microcode patches alignment.
+      // Because the microcode patch is the multiple of 1-KByte, the padding data should not
+      // exist if the microcode patch alignment value is not larger than 1-KByte. So, the microcode
+      // alignment value should be larger than 1-KByte. We could skip SIZE_1KB padding data to
+      // find the next possible microcode patch header.
+      //
+      MicrocodeEntryPoint = (CPU_MICROCODE_HEADER *) (((UINTN) MicrocodeEntryPoint) + SIZE_1KB);
+      continue;
+    }
+
+    Count++;
+    ASSERT(Count < 0xFF);
+
+    //
+    // Get the next patch.
+    //
+    MicrocodeEntryPoint = (CPU_MICROCODE_HEADER *) (((UINTN) MicrocodeEntryPoint) + TotalSize);
+  } while (((UINTN) MicrocodeEntryPoint < MicrocodeEnd));
+
+  return Count;
+}
+
+/**
+  Read Microcode.
+
+  @param  ImageIndex The index of Microcode image.
+  @param  Image      The Microcode image buffer.
+  @param  ImageSize  The size of Microcode image buffer in bytes.
+
+  @retval EFI_SUCCESS    The Microcode image is read.
+  @retval EFI_NOT_FOUND  The Microcode image is not found.
+**/
+EFI_STATUS
+MicrocodeRead(
+  IN UINTN      ImageIndex,
+  IN OUT VOID   *Image,
+  IN OUT UINTN  *ImageSize
+  )
+{
+  BOOLEAN                                 Result;
+  UINT64                                  MicrocodePatchAddress;
+  UINT64                                  MicrocodePatchRegionSize;
+  CPU_MICROCODE_HEADER                    *MicrocodeEntryPoint;
+  UINTN                                   MicrocodeEnd;
+  UINTN                                   TotalSize;
+  UINTN                                   Count;
+
+  Result = GetMicrocodeRegion(&MicrocodePatchAddress, &MicrocodePatchRegionSize);
+  if (!Result) {
+    DEBUG((EFI_D_ERROR, "Fail to get Microcode Region\n"));
+    return EFI_NOT_FOUND;
+  }
+  DEBUG((EFI_D_ERROR, "Microcode Region - 0x%lx - 0x%lx\n", MicrocodePatchAddress, MicrocodePatchRegionSize));
+
+  Count = 0;
+
+  MicrocodeEnd = (UINTN)(MicrocodePatchAddress + MicrocodePatchRegionSize);
+  MicrocodeEntryPoint = (CPU_MICROCODE_HEADER *)(UINTN)MicrocodePatchAddress;
+  do {
+    if (MicrocodeEntryPoint->HeaderVersion == 0x1 && MicrocodeEntryPoint->LoaderRevision == 0x1) {
+      //
+      // It is the microcode header. It is not the padding data between microcode patches
+      // becasue the padding data should not include 0x00000001 and it should be the repeated
+      // byte format (like 0xXYXYXYXY....).
+      //
+      if (MicrocodeEntryPoint->DataSize == 0) {
+        TotalSize = 2048;
+      } else {
+        TotalSize = MicrocodeEntryPoint->TotalSize;
+      }
+
+    } else {
+      //
+      // It is the padding data between the microcode patches for microcode patches alignment.
+      // Because the microcode patch is the multiple of 1-KByte, the padding data should not
+      // exist if the microcode patch alignment value is not larger than 1-KByte. So, the microcode
+      // alignment value should be larger than 1-KByte. We could skip SIZE_1KB padding data to
+      // find the next possible microcode patch header.
+      //
+      MicrocodeEntryPoint = (CPU_MICROCODE_HEADER *)(((UINTN)MicrocodeEntryPoint) + SIZE_1KB);
+      continue;
+    }
+
+    Count++;
+    ASSERT(Count < 0xFF);
+
+    //
+    // Get the next patch.
+    //
+    MicrocodeEntryPoint = (CPU_MICROCODE_HEADER *)(((UINTN)MicrocodeEntryPoint) + TotalSize);
+  } while (((UINTN)MicrocodeEntryPoint < MicrocodeEnd));
+
+  return EFI_NOT_FOUND;
+}
+
+/**
+  Verify Microcode.
+
+  @param  Image              The Microcode image buffer.
+  @param  ImageSize          The size of Microcode image buffer in bytes.
+  @param  TryLoad            Try to load Microcode or not.
+  @param  LastAttemptStatus  The last attempt status, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+  @param  AbortReason        A pointer to a pointer to a null-terminated string providing more
+                             details for the aborted operation. The buffer is allocated by this function
+                             with AllocatePool(), and it is the caller's responsibility to free it with a
+                             call to FreePool().
+
+  @retval EFI_SUCCESS               The Microcode image passes verification.
+  @retval EFI_VOLUME_CORRUPTED      The Microcode image is corrupt.
+  @retval EFI_INCOMPATIBLE_VERSION  The Microcode image version is incorrect.
+  @retval EFI_UNSUPPORTED           The Microcode ProcessorSignature or ProcessorFlags is incorrect.
+  @retval EFI_SECURITY_VIOLATION    The Microcode image fails to load.
+**/
+EFI_STATUS
+VerifyMicrocode(
+  IN VOID    *Image,
+  IN UINTN   ImageSize,
+  IN BOOLEAN TryLoad,
+  OUT UINT32 *LastAttemptStatus,
+  OUT CHAR16 **AbortReason
+  )
+{
+  UINTN                                   Index;
+  CPU_MICROCODE_HEADER                    *MicrocodeEntryPoint;
+  UINTN                                   TotalSize;
+  UINTN                                   DataSize;
+  UINT32                                  CurrentRevision;
+  UINT32                                  CurrentProcessorSignature;
+  UINT8                                   CurrentPlatformId;
+  UINT32                                  CheckSum32;
+  UINTN                                   ExtendedTableLength;
+  UINT32                                  ExtendedTableCount;
+  CPU_MICROCODE_EXTENDED_TABLE            *ExtendedTable;
+  CPU_MICROCODE_EXTENDED_TABLE_HEADER     *ExtendedTableHeader;
+  BOOLEAN                                 CorrectMicrocode;
+
+  //
+  // Check HeaderVersion
+  //
+  MicrocodeEntryPoint = Image;
+  if (MicrocodeEntryPoint->HeaderVersion != 0x1) {
+    DEBUG((EFI_D_ERROR, "VerifyMicrocode - fail on HeaderVersion\n"));
+    *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INVALID_FORMAT;
+    if (AbortReason != NULL) {
+      *AbortReason = AllocateCopyPool(sizeof(L"InvalidHeaderVersion"), L"InvalidHeaderVersion");
+    }
+    return EFI_INCOMPATIBLE_VERSION;
+  }
+  //
+  // Check LoaderRevision
+  //
+  if (MicrocodeEntryPoint->LoaderRevision != 0x1) {
+    DEBUG((EFI_D_ERROR, "VerifyMicrocode - fail on LoaderRevision\n"));
+    *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INVALID_FORMAT;
+    if (AbortReason != NULL) {
+      *AbortReason = AllocateCopyPool(sizeof(L"InvalidLoaderVersion"), L"InvalidLoaderVersion");
+    }
+    return EFI_INCOMPATIBLE_VERSION;
+  }
+  //
+  // Check Size
+  //
+  if (MicrocodeEntryPoint->DataSize == 0) {
+    TotalSize = 2048;
+  } else {
+    TotalSize = MicrocodeEntryPoint->TotalSize;
+  }
+  if (TotalSize <= sizeof(CPU_MICROCODE_HEADER)) {
+    DEBUG((EFI_D_ERROR, "VerifyMicrocode - TotalSize too small\n"));
+    *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INVALID_FORMAT;
+    if (AbortReason != NULL) {
+      *AbortReason = AllocateCopyPool(sizeof(L"InvalidTotalSize"), L"InvalidTotalSize");
+    }
+    return EFI_VOLUME_CORRUPTED;
+  }
+  if (TotalSize != ImageSize) {
+    DEBUG((EFI_D_ERROR, "VerifyMicrocode - fail on TotalSize\n"));
+    *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INVALID_FORMAT;
+    if (AbortReason != NULL) {
+      *AbortReason = AllocateCopyPool(sizeof(L"InvalidTotalSize"), L"InvalidTotalSize");
+    }
+    return EFI_VOLUME_CORRUPTED;
+  }
+  //
+  // Check CheckSum32
+  //
+  if (MicrocodeEntryPoint->DataSize == 0) {
+    DataSize = 2048 - sizeof(CPU_MICROCODE_HEADER);
+  } else {
+    DataSize = MicrocodeEntryPoint->DataSize;
+  }
+  if (DataSize > TotalSize - sizeof(CPU_MICROCODE_HEADER)) {
+    DEBUG((EFI_D_ERROR, "VerifyMicrocode - DataSize too big\n"));
+    *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INVALID_FORMAT;
+    if (AbortReason != NULL) {
+      *AbortReason = AllocateCopyPool(sizeof(L"InvalidDataSize"), L"InvalidDataSize");
+    }
+    return EFI_VOLUME_CORRUPTED;
+  }
+  if ((DataSize & 0x3) != 0) {
+    DEBUG((EFI_D_ERROR, "VerifyMicrocode - DataSize not aligned\n"));
+    *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INVALID_FORMAT;
+    if (AbortReason != NULL) {
+      *AbortReason = AllocateCopyPool(sizeof(L"InvalidDataSize"), L"InvalidDataSize");
+    }
+    return EFI_VOLUME_CORRUPTED;
+  }
+  CheckSum32 = CalculateSum32((UINT32 *)MicrocodeEntryPoint, DataSize + sizeof(CPU_MICROCODE_HEADER));
+  if (CheckSum32 != 0) {
+    DEBUG((EFI_D_ERROR, "VerifyMicrocode - fail on CheckSum32\n"));
+    *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INVALID_FORMAT;
+    if (AbortReason != NULL) {
+      *AbortReason = AllocateCopyPool(sizeof(L"InvalidChecksum"), L"InvalidChecksum");
+    }
+    return EFI_VOLUME_CORRUPTED;
+  }
+
+  //
+  // Check ProcessorSignature/ProcessorFlags
+  //
+  CorrectMicrocode = FALSE;
+  CurrentProcessorSignature = GetCurrentProcessorSignature();
+  CurrentPlatformId = GetCurrentPlatformId();
+  if ((MicrocodeEntryPoint->ProcessorSignature.Uint32 != CurrentProcessorSignature) ||
+      ((MicrocodeEntryPoint->ProcessorFlags & (1 << CurrentPlatformId)) == 0)) {
+    ExtendedTableLength = TotalSize - (DataSize + sizeof(CPU_MICROCODE_HEADER));
+    if (ExtendedTableLength != 0) {
+      //
+      // Extended Table exist, check if the CPU in support list
+      //
+      ExtendedTableHeader = (CPU_MICROCODE_EXTENDED_TABLE_HEADER *)((UINT8 *)(MicrocodeEntryPoint) + DataSize + sizeof(CPU_MICROCODE_HEADER));
+      //
+      // Calculate Extended Checksum
+      //
+      if ((ExtendedTableLength > sizeof(CPU_MICROCODE_EXTENDED_TABLE_HEADER)) && ((ExtendedTableLength & 0x3) != 0)) {
+        CheckSum32 = CalculateSum32((UINT32 *)ExtendedTableHeader, ExtendedTableLength);
+        if (CheckSum32 == 0) {
+          //
+          // Checksum correct
+          //
+          ExtendedTableCount = ExtendedTableHeader->ExtendedSignatureCount;
+          if (ExtendedTableCount <= (ExtendedTableLength - sizeof(CPU_MICROCODE_EXTENDED_TABLE_HEADER)) / sizeof(CPU_MICROCODE_EXTENDED_TABLE)) {
+            ExtendedTable = (CPU_MICROCODE_EXTENDED_TABLE *)(ExtendedTableHeader + 1);
+            for (Index = 0; Index < ExtendedTableCount; Index++) {
+              CheckSum32 = CalculateSum32((UINT32 *)ExtendedTable, sizeof(CPU_MICROCODE_EXTENDED_TABLE));
+              if (CheckSum32 == 0) {
+                //
+                // Verify Header
+                //
+                if ((ExtendedTable->ProcessorSignature.Uint32 == CurrentProcessorSignature) &&
+                    (ExtendedTable->ProcessorFlag & (1 << CurrentPlatformId))) {
+                  //
+                  // Find one
+                  //
+                  CorrectMicrocode = TRUE;
+                  break;
+                }
+              }
+              ExtendedTable++;
+            }
+          }
+        }
+      }
+    }
+    if (!CorrectMicrocode) {
+      DEBUG((EFI_D_ERROR, "VerifyMicrocode - fail on CurrentProcessorSignature/ProcessorFlags\n"));
+      *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INCORRECT_VERSION;
+      if (AbortReason != NULL) {
+        if (MicrocodeEntryPoint->ProcessorSignature.Uint32 != CurrentProcessorSignature) {
+          *AbortReason = AllocateCopyPool(sizeof(L"UnsupportedProcessSignature"), L"UnsupportedProcessSignature");
+        } else {
+          *AbortReason = AllocateCopyPool(sizeof(L"UnsupportedProcessorFlags"), L"UnsupportedProcessorFlags");
+        }
+      }
+      return EFI_UNSUPPORTED;
+    }
+  }
+
+  //
+  // Check UpdateRevision
+  //
+  CurrentRevision = GetCurrentMicrocodeSignature();
+  if (MicrocodeEntryPoint->UpdateRevision < CurrentRevision) {
+    DEBUG((EFI_D_ERROR, "VerifyMicrocode - fail on UpdateRevision\n"));
+    *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INCORRECT_VERSION;
+    if (AbortReason != NULL) {
+      *AbortReason = AllocateCopyPool(sizeof(L"IncorrectRevision"), L"IncorrectRevision");
+    }
+    return EFI_INCOMPATIBLE_VERSION;
+  }
+
+  //
+  // try load MCU
+  //
+  if (TryLoad) {
+    CurrentRevision = LoadMicrocode((UINTN)MicrocodeEntryPoint + sizeof(CPU_MICROCODE_HEADER));
+    if (MicrocodeEntryPoint->UpdateRevision != CurrentRevision) {
+      DEBUG((EFI_D_ERROR, "VerifyMicrocode - fail on LoadMicrocode\n"));
+      *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_AUTH_ERROR;
+      if (AbortReason != NULL) {
+        *AbortReason = AllocateCopyPool(sizeof(L"InvalidData"), L"InvalidData");
+      }
+      return EFI_SECURITY_VIOLATION;
+    }
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Get current Microcode in used.
+
+  @return current Microcode in used.
+**/
+VOID *
+GetCurrentMicrocodeInUse(
+  VOID
+  )
+{
+  BOOLEAN                                 Result;
+  EFI_STATUS                              Status;
+  UINT64                                  MicrocodePatchAddress;
+  UINT64                                  MicrocodePatchRegionSize;
+  CPU_MICROCODE_HEADER                    *MicrocodeEntryPoint;
+  UINTN                                   MicrocodeEnd;
+  UINTN                                   TotalSize;
+  UINTN                                   Count;
+  UINT32                                  AttemptStatus;
+
+  Result = GetMicrocodeRegion(&MicrocodePatchAddress, &MicrocodePatchRegionSize);
+  if (!Result) {
+    DEBUG((EFI_D_ERROR, "Fail to get Microcode Region\n"));
+    return NULL;
+  }
+  DEBUG((EFI_D_ERROR, "Microcode Region - 0x%lx - 0x%lx\n", MicrocodePatchAddress, MicrocodePatchRegionSize));
+
+  Count = 0;
+
+  MicrocodeEnd = (UINTN)(MicrocodePatchAddress + MicrocodePatchRegionSize);
+  MicrocodeEntryPoint = (CPU_MICROCODE_HEADER *)(UINTN)MicrocodePatchAddress;
+  do {
+    if (MicrocodeEntryPoint->HeaderVersion == 0x1 && MicrocodeEntryPoint->LoaderRevision == 0x1) {
+      //
+      // It is the microcode header. It is not the padding data between microcode patches
+      // becasue the padding data should not include 0x00000001 and it should be the repeated
+      // byte format (like 0xXYXYXYXY....).
+      //
+      if (MicrocodeEntryPoint->DataSize == 0) {
+        TotalSize = 2048;
+      } else {
+        TotalSize = MicrocodeEntryPoint->TotalSize;
+      }
+      Status = VerifyMicrocode(MicrocodeEntryPoint, TotalSize, FALSE, &AttemptStatus, NULL);
+      if (!EFI_ERROR(Status)) {
+        return MicrocodeEntryPoint;
+      }
+
+    } else {
+      //
+      // It is the padding data between the microcode patches for microcode patches alignment.
+      // Because the microcode patch is the multiple of 1-KByte, the padding data should not
+      // exist if the microcode patch alignment value is not larger than 1-KByte. So, the microcode
+      // alignment value should be larger than 1-KByte. We could skip SIZE_1KB padding data to
+      // find the next possible microcode patch header.
+      //
+      MicrocodeEntryPoint = (CPU_MICROCODE_HEADER *)(((UINTN)MicrocodeEntryPoint) + SIZE_1KB);
+      continue;
+    }
+
+    Count++;
+    ASSERT(Count < 0xFF);
+
+    //
+    // Get the next patch.
+    //
+    MicrocodeEntryPoint = (CPU_MICROCODE_HEADER *)(((UINTN)MicrocodeEntryPoint) + TotalSize);
+  } while (((UINTN)MicrocodeEntryPoint < MicrocodeEnd));
+
+  return NULL;
+}
+
+/**
+  Get current Microcode used region size.
+
+  @return current Microcode used region size.
+**/
+UINTN
+GetCurrentMicrocodeUsedRegionSize(
+  VOID
+  )
+{
+  BOOLEAN                                 Result;
+  UINT64                                  MicrocodePatchAddress;
+  UINT64                                  MicrocodePatchRegionSize;
+  CPU_MICROCODE_HEADER                    *MicrocodeEntryPoint;
+  UINTN                                   MicrocodeEnd;
+  UINTN                                   TotalSize;
+  UINTN                                   Count;
+  UINTN                                   MicrocodeUsedEnd;
+
+  Result = GetMicrocodeRegion(&MicrocodePatchAddress, &MicrocodePatchRegionSize);
+  if (!Result) {
+    DEBUG((EFI_D_ERROR, "Fail to get Microcode Region\n"));
+    return 0;
+  }
+  DEBUG((EFI_D_ERROR, "Microcode Region - 0x%lx - 0x%lx\n", MicrocodePatchAddress, MicrocodePatchRegionSize));
+
+  MicrocodeUsedEnd = (UINTN)MicrocodePatchAddress;
+  Count = 0;
+
+  MicrocodeEnd = (UINTN)(MicrocodePatchAddress + MicrocodePatchRegionSize);
+  MicrocodeEntryPoint = (CPU_MICROCODE_HEADER *)(UINTN)MicrocodePatchAddress;
+  do {
+    if (MicrocodeEntryPoint->HeaderVersion == 0x1 && MicrocodeEntryPoint->LoaderRevision == 0x1) {
+      //
+      // It is the microcode header. It is not the padding data between microcode patches
+      // becasue the padding data should not include 0x00000001 and it should be the repeated
+      // byte format (like 0xXYXYXYXY....).
+      //
+      if (MicrocodeEntryPoint->DataSize == 0) {
+        TotalSize = 2048;
+      } else {
+        TotalSize = MicrocodeEntryPoint->TotalSize;
+      }
+
+    } else {
+      //
+      // It is the padding data between the microcode patches for microcode patches alignment.
+      // Because the microcode patch is the multiple of 1-KByte, the padding data should not
+      // exist if the microcode patch alignment value is not larger than 1-KByte. So, the microcode
+      // alignment value should be larger than 1-KByte. We could skip SIZE_1KB padding data to
+      // find the next possible microcode patch header.
+      //
+      MicrocodeEntryPoint = (CPU_MICROCODE_HEADER *)(((UINTN)MicrocodeEntryPoint) + SIZE_1KB);
+      continue;
+    }
+
+    Count++;
+    ASSERT(Count < 0xFF);
+    MicrocodeUsedEnd = (UINTN)MicrocodeEntryPoint;
+
+    //
+    // Get the next patch.
+    //
+    MicrocodeEntryPoint = (CPU_MICROCODE_HEADER *)(((UINTN)MicrocodeEntryPoint) + TotalSize);
+  } while (((UINTN)MicrocodeEntryPoint < MicrocodeEnd));
+
+  return MicrocodeUsedEnd - (UINTN)MicrocodePatchAddress;
+}
+
+/**
+  Update Microcode.
+
+  @param  Address            The flash address of Microcode.
+  @param  Image              The Microcode image buffer.
+  @param  ImageSize          The size of Microcode image buffer in bytes.
+  @param  LastAttemptStatus  The last attempt status, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+
+  @retval EFI_SUCCESS           The Microcode image is updated.
+  @retval EFI_WRITE_PROTECTED   The flash device is read only.
+**/
+EFI_STATUS
+UpdateMicrocode(
+  IN UINT64  Address,
+  IN VOID    *Image,
+  IN UINTN   ImageSize,
+  OUT UINT32 *LastAttemptStatus
+  )
+{
+  EFI_STATUS  Status;
+
+  DEBUG((EFI_D_INFO, "PlatformUpdate:"));
+  DEBUG((EFI_D_INFO, "  Address - 0x%lx,", Address));
+  DEBUG((EFI_D_INFO, "  Legnth - 0x%x\n", ImageSize));
+
+  Status = MicrocodeFlashWrite (
+             Address,
+             Image,
+             ImageSize
+             );
+  if (!EFI_ERROR(Status)) {
+    *LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;
+  } else {
+    *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL;
+  }
+  return Status;
+}
+
+/**
+  Write Microcode.
+
+  @param  ImageIndex         The index of Microcode image.
+  @param  Image              The Microcode image buffer.
+  @param  ImageSize          The size of Microcode image buffer in bytes.
+  @param  LastAttemptVersion The last attempt version, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+  @param  LastAttemptStatus  The last attempt status, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+  @param  AbortReason        A pointer to a pointer to a null-terminated string providing more
+                             details for the aborted operation. The buffer is allocated by this function
+                             with AllocatePool(), and it is the caller's responsibility to free it with a
+                             call to FreePool().
+
+  @retval EFI_SUCCESS               The Microcode image is written.
+  @retval EFI_VOLUME_CORRUPTED      The Microcode image is corrupt.
+  @retval EFI_INCOMPATIBLE_VERSION  The Microcode image version is incorrect.
+  @retval EFI_SECURITY_VIOLATION    The Microcode image fails to load.
+  @retval EFI_WRITE_PROTECTED   The flash device is read only.
+**/
+EFI_STATUS
+MicrocodeWrite(
+  IN  UINTN  ImageIndex,
+  IN  VOID   *Image,
+  IN  UINTN  ImageSize,
+  OUT UINT32 *LastAttemptVersion,
+  OUT UINT32 *LastAttemptStatus,
+  OUT CHAR16 **AbortReason
+  )
+{
+  BOOLEAN                                 Result;
+  EFI_STATUS                              Status;
+  UINT64                                  MicrocodePatchAddress;
+  UINT64                                  MicrocodePatchRegionSize;
+  CPU_MICROCODE_HEADER                    *CurrentMicrocodeEntryPoint;
+  UINTN                                   CurrentTotalSize;
+  UINTN                                   UsedRegionSize;
+  VOID                                    *AlignedImage;
+
+  Result = GetMicrocodeRegion(&MicrocodePatchAddress, &MicrocodePatchRegionSize);
+  if (!Result) {
+    DEBUG((EFI_D_ERROR, "Fail to get Microcode Region\n"));
+    return EFI_NOT_FOUND;
+  }
+
+  CurrentTotalSize = 0;
+  CurrentMicrocodeEntryPoint = GetCurrentMicrocodeInUse();
+  if (CurrentMicrocodeEntryPoint != NULL) {
+    if (CurrentMicrocodeEntryPoint->DataSize == 0) {
+      CurrentTotalSize = 2048;
+    } else {
+      CurrentTotalSize = CurrentMicrocodeEntryPoint->TotalSize;
+    }
+  }
+
+  //
+  // MCU must be 16 bytes aligned
+  //
+  AlignedImage = AllocateCopyPool(ImageSize, Image);
+
+  *LastAttemptVersion = ((CPU_MICROCODE_HEADER *)Image)->UpdateRevision;
+  Status = VerifyMicrocode(AlignedImage, ImageSize, TRUE, LastAttemptStatus, AbortReason);
+  if (EFI_ERROR(Status)) {
+    DEBUG((EFI_D_ERROR, "Fail to verify Microcode Region\n"));
+    FreePool(AlignedImage);
+    return Status;
+  }
+  DEBUG((EFI_D_INFO, "Pass VerifyMicrocode\n"));
+
+  if (CurrentTotalSize < ImageSize) {
+    UsedRegionSize = GetCurrentMicrocodeUsedRegionSize();
+    if (MicrocodePatchRegionSize - UsedRegionSize >= ImageSize) {
+      //
+      // Append
+      //
+      DEBUG((EFI_D_INFO, "Append new microcode\n"));
+      Status = UpdateMicrocode(MicrocodePatchAddress + UsedRegionSize, AlignedImage, ImageSize, LastAttemptStatus);
+    } else if (MicrocodePatchRegionSize >= ImageSize) {
+      //
+      // Ignor all others and just add this one from beginning.
+      //
+      DEBUG((EFI_D_INFO, "Add new microcode from beginning\n"));
+      Status = UpdateMicrocode(MicrocodePatchAddress, AlignedImage, ImageSize, LastAttemptStatus);
+    } else {
+      DEBUG((EFI_D_ERROR, "Microcode too big\n"));
+      *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INSUFFICIENT_RESOURCES;
+      Status = EFI_OUT_OF_RESOURCES;
+    }
+  } else {
+    //
+    // Replace
+    //
+    DEBUG((EFI_D_INFO, "Replace old microcode\n"));
+    Status = UpdateMicrocode((UINTN)CurrentMicrocodeEntryPoint, AlignedImage, ImageSize, LastAttemptStatus);
+  }
+
+  FreePool(AlignedImage);
+
+  return Status;
+}
+
+
diff --git a/UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.h b/UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.h
new file mode 100644
index 0000000..23ec0ba
--- /dev/null
+++ b/UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.h
@@ -0,0 +1,299 @@
+/** @file
+  Microcode update header file.
+
+  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _MICROCODE_FMP_H_
+#define _MICROCODE_FMP_H_
+
+#include <PiDxe.h>
+
+#include <Guid/SystemResourceTable.h>
+#include <Guid/MicrocodeFmp.h>
+
+#include <Protocol/FirmwareManagement.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/DevicePathLib.h>
+#include <Library/HobLib.h>
+#include <Library/MicrocodeFlashAccessLib.h>
+
+#include <Register/Cpuid.h>
+#include <Register/Msr.h>
+#include <Register/Microcode.h>
+
+/**
+  Returns information about the current firmware image(s) of the device.
+
+  This function allows a copy of the current firmware image to be created and saved.
+  The saved copy could later been used, for example, in firmware image recovery or rollback.
+
+  @param[in]      This               A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
+  @param[in, out] ImageInfoSize      A pointer to the size, in bytes, of the ImageInfo buffer.
+                                     On input, this is the size of the buffer allocated by the caller.
+                                     On output, it is the size of the buffer returned by the firmware
+                                     if the buffer was large enough, or the size of the buffer needed
+                                     to contain the image(s) information if the buffer was too small.
+  @param[in, out] ImageInfo          A pointer to the buffer in which firmware places the current image(s)
+                                     information. The information is an array of EFI_FIRMWARE_IMAGE_DESCRIPTORs.
+  @param[out]     DescriptorVersion  A pointer to the location in which firmware returns the version number
+                                     associated with the EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+  @param[out]     DescriptorCount    A pointer to the location in which firmware returns the number of
+                                     descriptors or firmware images within this device.
+  @param[out]     DescriptorSize     A pointer to the location in which firmware returns the size, in bytes,
+                                     of an individual EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+  @param[out]     PackageVersion     A version number that represents all the firmware images in the device.
+                                     The format is vendor specific and new version must have a greater value
+                                     than the old version. If PackageVersion is not supported, the value is
+                                     0xFFFFFFFF. A value of 0xFFFFFFFE indicates that package version comparison
+                                     is to be performed using PackageVersionName. A value of 0xFFFFFFFD indicates
+                                     that package version update is in progress.
+  @param[out]     PackageVersionName A pointer to a pointer to a null-terminated string representing the
+                                     package version name. The buffer is allocated by this function with
+                                     AllocatePool(), and it is the caller's responsibility to free it with a call
+                                     to FreePool().
+
+  @retval EFI_SUCCESS                The device was successfully updated with the new image.
+  @retval EFI_BUFFER_TOO_SMALL       The ImageInfo buffer was too small. The current buffer size
+                                     needed to hold the image(s) information is returned in ImageInfoSize.
+  @retval EFI_INVALID_PARAMETER      ImageInfoSize is NULL.
+  @retval EFI_DEVICE_ERROR           Valid information could not be returned. Possible corrupted image.
+
+**/
+EFI_STATUS
+EFIAPI
+FmpGetImageInfo(
+  IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL       *This,
+  IN OUT    UINTN                           *ImageInfoSize,
+  IN OUT    EFI_FIRMWARE_IMAGE_DESCRIPTOR   *ImageInfo,
+  OUT       UINT32                          *DescriptorVersion,
+  OUT       UINT8                           *DescriptorCount,
+  OUT       UINTN                           *DescriptorSize,
+  OUT       UINT32                          *PackageVersion,
+  OUT       CHAR16                          **PackageVersionName
+  );
+
+/**
+  Retrieves a copy of the current firmware image of the device.
+
+  This function allows a copy of the current firmware image to be created and saved.
+  The saved copy could later been used, for example, in firmware image recovery or rollback.
+
+  @param[in]     This            A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
+  @param[in]     ImageIndex      A unique number identifying the firmware image(s) within the device.
+                                 The number is between 1 and DescriptorCount.
+  @param[in,out] Image           Points to the buffer where the current image is copied to.
+  @param[in,out] ImageSize       On entry, points to the size of the buffer pointed to by Image, in bytes.
+                                 On return, points to the length of the image, in bytes.
+
+  @retval EFI_SUCCESS            The device was successfully updated with the new image.
+  @retval EFI_BUFFER_TOO_SMALL   The buffer specified by ImageSize is too small to hold the
+                                 image. The current buffer size needed to hold the image is returned
+                                 in ImageSize.
+  @retval EFI_INVALID_PARAMETER  The Image was NULL.
+  @retval EFI_NOT_FOUND          The current image is not copied to the buffer.
+  @retval EFI_UNSUPPORTED        The operation is not supported.
+  @retval EFI_SECURITY_VIOLATIO  The operation could not be performed due to an authentication failure.
+
+**/
+EFI_STATUS
+EFIAPI
+FmpGetImage(
+  IN  EFI_FIRMWARE_MANAGEMENT_PROTOCOL  *This,
+  IN  UINT8                             ImageIndex,
+  IN  OUT  VOID                         *Image,
+  IN  OUT  UINTN                        *ImageSize
+  );
+
+/**
+  Updates the firmware image of the device.
+
+  This function updates the hardware with the new firmware image.
+  This function returns EFI_UNSUPPORTED if the firmware image is not updatable.
+  If the firmware image is updatable, the function should perform the following minimal validations
+  before proceeding to do the firmware image update.
+  - Validate the image authentication if image has attribute
+    IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED. The function returns
+    EFI_SECURITY_VIOLATION if the validation fails.
+  - Validate the image is a supported image for this device. The function returns EFI_ABORTED if
+    the image is unsupported. The function can optionally provide more detailed information on
+    why the image is not a supported image.
+  - Validate the data from VendorCode if not null. Image validation must be performed before
+    VendorCode data validation. VendorCode data is ignored or considered invalid if image
+    validation failed. The function returns EFI_ABORTED if the data is invalid.
+
+  VendorCode enables vendor to implement vendor-specific firmware image update policy. Null if
+  the caller did not specify the policy or use the default policy. As an example, vendor can implement
+  a policy to allow an option to force a firmware image update when the abort reason is due to the new
+  firmware image version is older than the current firmware image version or bad image checksum.
+  Sensitive operations such as those wiping the entire firmware image and render the device to be
+  non-functional should be encoded in the image itself rather than passed with the VendorCode.
+  AbortReason enables vendor to have the option to provide a more detailed description of the abort
+  reason to the caller.
+
+  @param[in]  This               A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
+  @param[in]  ImageIndex         A unique number identifying the firmware image(s) within the device.
+                                 The number is between 1 and DescriptorCount.
+  @param[in]  Image              Points to the new image.
+  @param[in]  ImageSize          Size of the new image in bytes.
+  @param[in]  VendorCode         This enables vendor to implement vendor-specific firmware image update policy.
+                                 Null indicates the caller did not specify the policy or use the default policy.
+  @param[in]  Progress           A function used by the driver to report the progress of the firmware update.
+  @param[out] AbortReason        A pointer to a pointer to a null-terminated string providing more
+                                 details for the aborted operation. The buffer is allocated by this function
+                                 with AllocatePool(), and it is the caller's responsibility to free it with a
+                                 call to FreePool().
+
+  @retval EFI_SUCCESS            The device was successfully updated with the new image.
+  @retval EFI_ABORTED            The operation is aborted.
+  @retval EFI_INVALID_PARAMETER  The Image was NULL.
+  @retval EFI_UNSUPPORTED        The operation is not supported.
+  @retval EFI_SECURITY_VIOLATIO  The operation could not be performed due to an authentication failure.
+
+**/
+EFI_STATUS
+EFIAPI
+FmpSetImage(
+  IN  EFI_FIRMWARE_MANAGEMENT_PROTOCOL                 *This,
+  IN  UINT8                                            ImageIndex,
+  IN  CONST VOID                                       *Image,
+  IN  UINTN                                            ImageSize,
+  IN  CONST VOID                                       *VendorCode,
+  IN  EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS    Progress,
+  OUT CHAR16                                           **AbortReason
+  );
+
+/**
+  Checks if the firmware image is valid for the device.
+
+  This function allows firmware update application to validate the firmware image without
+  invoking the SetImage() first.
+
+  @param[in]  This               A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
+  @param[in]  ImageIndex         A unique number identifying the firmware image(s) within the device.
+                                 The number is between 1 and DescriptorCount.
+  @param[in]  Image              Points to the new image.
+  @param[in]  ImageSize          Size of the new image in bytes.
+  @param[out] ImageUpdatable     Indicates if the new image is valid for update. It also provides,
+                                 if available, additional information if the image is invalid.
+
+  @retval EFI_SUCCESS            The image was successfully checked.
+  @retval EFI_INVALID_PARAMETER  The Image was NULL.
+  @retval EFI_UNSUPPORTED        The operation is not supported.
+  @retval EFI_SECURITY_VIOLATIO  The operation could not be performed due to an authentication failure.
+
+**/
+EFI_STATUS
+EFIAPI
+FmpCheckImage(
+  IN  EFI_FIRMWARE_MANAGEMENT_PROTOCOL  *This,
+  IN  UINT8                             ImageIndex,
+  IN  CONST VOID                        *Image,
+  IN  UINTN                             ImageSize,
+  OUT UINT32                            *ImageUpdatable
+  );
+
+/**
+  Returns information about the firmware package.
+
+  This function returns package information.
+
+  @param[in]  This                     A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
+  @param[out] PackageVersion           A version number that represents all the firmware images in the device.
+                                       The format is vendor specific and new version must have a greater value
+                                       than the old version. If PackageVersion is not supported, the value is
+                                       0xFFFFFFFF. A value of 0xFFFFFFFE indicates that package version
+                                       comparison is to be performed using PackageVersionName. A value of
+                                       0xFFFFFFFD indicates that package version update is in progress.
+  @param[out] PackageVersionName       A pointer to a pointer to a null-terminated string representing
+                                       the package version name. The buffer is allocated by this function with
+                                       AllocatePool(), and it is the caller's responsibility to free it with a
+                                       call to FreePool().
+  @param[out] PackageVersionNameMaxLen The maximum length of package version name if device supports update of
+                                       package version name. A value of 0 indicates the device does not support
+                                       update of package version name. Length is the number of Unicode characters,
+                                       including the terminating null character.
+  @param[out] AttributesSupported      Package attributes that are supported by this device. See 'Package Attribute
+                                       Definitions' for possible returned values of this parameter. A value of 1
+                                       indicates the attribute is supported and the current setting value is
+                                       indicated in AttributesSetting. A value of 0 indicates the attribute is not
+                                       supported and the current setting value in AttributesSetting is meaningless.
+  @param[out] AttributesSetting        Package attributes. See 'Package Attribute Definitions' for possible returned
+                                       values of this parameter
+
+  @retval EFI_SUCCESS                  The package information was successfully returned.
+  @retval EFI_UNSUPPORTED              The operation is not supported.
+
+**/
+EFI_STATUS
+EFIAPI
+FmpGetPackageInfo(
+  IN  EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This,
+  OUT UINT32                           *PackageVersion,
+  OUT CHAR16                           **PackageVersionName,
+  OUT UINT32                           *PackageVersionNameMaxLen,
+  OUT UINT64                           *AttributesSupported,
+  OUT UINT64                           *AttributesSetting
+  );
+
+/**
+  Updates information about the firmware package.
+
+  This function updates package information.
+  This function returns EFI_UNSUPPORTED if the package information is not updatable.
+  VendorCode enables vendor to implement vendor-specific package information update policy.
+  Null if the caller did not specify this policy or use the default policy.
+
+  @param[in]  This               A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
+  @param[in]  Image              Points to the authentication image.
+                                 Null if authentication is not required.
+  @param[in]  ImageSize          Size of the authentication image in bytes.
+                                 0 if authentication is not required.
+  @param[in]  VendorCode         This enables vendor to implement vendor-specific firmware
+                                 image update policy.
+                                 Null indicates the caller did not specify this policy or use
+                                 the default policy.
+  @param[in]  PackageVersion     The new package version.
+  @param[in]  PackageVersionName A pointer to the new null-terminated Unicode string representing
+                                 the package version name.
+                                 The string length is equal to or less than the value returned in
+                                 PackageVersionNameMaxLen.
+
+  @retval EFI_SUCCESS            The device was successfully updated with the new package
+                                 information.
+  @retval EFI_INVALID_PARAMETER  The PackageVersionName length is longer than the value
+                                 returned in PackageVersionNameMaxLen.
+  @retval EFI_UNSUPPORTED        The operation is not supported.
+  @retval EFI_SECURITY_VIOLATIO  The operation could not be performed due to an authentication failure.
+
+**/
+EFI_STATUS
+EFIAPI
+FmpSetPackageInfo(
+  IN  EFI_FIRMWARE_MANAGEMENT_PROTOCOL   *This,
+  IN  CONST VOID                         *Image,
+  IN  UINTN                              ImageSize,
+  IN  CONST VOID                         *VendorCode,
+  IN  UINT32                             PackageVersion,
+  IN  CONST CHAR16                       *PackageVersionName
+  );
+
+#endif
+
diff --git a/UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.inf b/UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.inf
new file mode 100644
index 0000000..736684c
--- /dev/null
+++ b/UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.inf
@@ -0,0 +1,68 @@
+## @file
+# Microcode FMP update driver.
+#
+# Produce FMP instance to update Microcode.
+#
+#  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = MicrocodeUpdate
+  MODULE_UNI_FILE                = MicrocodeUpdateDxe.uni
+  FILE_GUID                      = 0565365C-2FE1-4F88-B3BE-624C04623A20
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = MicrocodeFmpMain
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = X64
+#
+
+[Sources]
+  MicrocodeFmp.c
+  MicrocodeUpdate.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  UefiCpuPkg/UefiCpuPkg.dec
+
+[LibraryClasses]
+  BaseLib
+  UefiLib
+  BaseMemoryLib
+  DebugLib
+  PcdLib
+  MemoryAllocationLib
+  UefiBootServicesTableLib
+  HobLib
+  UefiRuntimeServicesTableLib
+  UefiDriverEntryPoint
+  MicrocodeFlashAccessLib
+
+[Guids]
+  gMicrocodeFmpImageTypeIdGuid
+
+[Protocols]
+  gEfiFirmwareManagementProtocolGuid            ## SOMTIMES_PRODUCE
+
+[Pcd]
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuMicrocodePatchAddress            ## CONSUMES
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuMicrocodePatchRegionSize         ## CONSUMES
+
+[Depex]
+  gEfiVariableArchProtocolGuid
+
+[UserExtensions.TianoCore."ExtraFiles"]
+  MicrocodeUpdateDxeExtra.uni
+
diff --git a/UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdateDxe.uni b/UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdateDxe.uni
new file mode 100644
index 0000000..1b0d494
--- /dev/null
+++ b/UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdateDxe.uni
@@ -0,0 +1,21 @@
+// /** @file
+// Microcode FMP update driver.
+//
+// Produce FMP instance to update Microcode.
+//
+// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+//
+// This program and the accompanying materials
+// are licensed and made available under the terms and conditions of the BSD License
+// which accompanies this distribution.  The full text of the license may be found at
+// http://opensource.org/licenses/bsd-license.php
+//
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT             #language en-US "Microcode FMP update driver."
+
+#string STR_MODULE_DESCRIPTION          #language en-US "Produce FMP instance to update Microcode."
diff --git a/UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdateDxeExtra.uni b/UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdateDxeExtra.uni
new file mode 100644
index 0000000..b667f12
--- /dev/null
+++ b/UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdateDxeExtra.uni
@@ -0,0 +1,20 @@
+// /** @file
+// MicrocodeUpdateDxe Localized Strings and Content
+//
+// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+//
+// This program and the accompanying materials
+// are licensed and made available under the terms and conditions of the BSD License
+// which accompanies this distribution.  The full text of the license may be found at
+// http://opensource.org/licenses/bsd-license.php
+//
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+// **/
+
+#string STR_PROPERTIES_MODULE_NAME
+#language en-US
+"MicrocodeUpdate DXE Driver"
+
+
-- 
2.7.4.windows.1



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

* Re: [PATCH 23/45] SecurityPkg/SecurityPkg.dsc: Add FmpAuthentication*Lib.
  2016-09-21  6:45 ` [PATCH 23/45] SecurityPkg/SecurityPkg.dsc: Add FmpAuthentication*Lib Jiewen Yao
@ 2016-09-28  4:56   ` Zhang, Chao B
  0 siblings, 0 replies; 83+ messages in thread
From: Zhang, Chao B @ 2016-09-28  4:56 UTC (permalink / raw)
  To: Yao, Jiewen, edk2-devel@lists.01.org
  Cc: Tian, Feng, Zeng, Star, Kinney, Michael D, Gao, Liming

Jiewen:
  SecurityPackage Patches are good to me. 
  Reviewed by : Chao Zhang <chao.b.zhang@intel.com>





Thanks & Best regards
Chao Zhang


-----Original Message-----
From: Yao, Jiewen 
Sent: Wednesday, September 21, 2016 2:45 PM
To: edk2-devel@lists.01.org
Cc: Tian, Feng; Zeng, Star; Kinney, Michael D; Gao, Liming; Zhang, Chao B
Subject: [PATCH 23/45] SecurityPkg/SecurityPkg.dsc: Add FmpAuthentication*Lib.

Add FmpAuthentication*Lib to check build.

Cc: Feng Tian <feng.tian@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Chao Zhang <chao.b.zhang@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
---
 SecurityPkg/SecurityPkg.dsc | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/SecurityPkg/SecurityPkg.dsc b/SecurityPkg/SecurityPkg.dsc
index 3b36d0f..09d083e 100644
--- a/SecurityPkg/SecurityPkg.dsc
+++ b/SecurityPkg/SecurityPkg.dsc
@@ -211,6 +211,9 @@
   SecurityPkg/Library/DxeRsa2048Sha256GuidedSectionExtractLib/DxeRsa2048Sha256GuidedSectionExtractLib.inf
   SecurityPkg/Library/PeiRsa2048Sha256GuidedSectionExtractLib/PeiRsa2048Sha256GuidedSectionExtractLib.inf
 
+  SecurityPkg/Library/FmpAuthenticationPkcs7Lib/FmpAuthenticationPkcs7Lib.inf
+  SecurityPkg/Library/FmpAuthenticationRsa2048Sha256Lib/FmpAuthenticationRsa2048Sha256Lib.inf
+
   SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf
 
 [Components.IA32, Components.X64, Components.IPF]
-- 
2.7.4.windows.1



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

* Re: [PATCH 00/45] Add capsule update and recovery sample.
  2016-09-21  6:44 [PATCH 00/45] Add capsule update and recovery sample Jiewen Yao
                   ` (47 preceding siblings ...)
  2016-09-27  3:16 ` Gao, Liming
@ 2016-09-28  8:05 ` Yao, Jiewen
  2016-09-28 14:54   ` Kinney, Michael D
  48 siblings, 1 reply; 83+ messages in thread
From: Yao, Jiewen @ 2016-09-28  8:05 UTC (permalink / raw)
  To: Yao, Jiewen, edk2-devel@lists.01.org
  Cc: Tian, Feng, Gao, Liming, Zeng, Star, Kinney, Michael D, Fan, Jeff,
	Zhang, Chao B

Hi
I got reviewed-by for MdeModulePkg/SecurityPkg/UefiCpuPkg/Vlv2DevicePkg. Thanks each package owner.

I have not got reviewed-by for QuarkPlatformPkg yet. Can QuarkPlatformPkg owner review the platform update?
Or it takes quark owner more time to review QuarkPlatformPkg, I will plan to check in above 4 reviewed package at first.

QuarkPlatformPkg update is independent and can be checked in and enabled later.

Thank you
Yao Jiewen


> -----Original Message-----
> From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of
> Jiewen Yao
> Sent: Wednesday, September 21, 2016 2:45 PM
> To: edk2-devel@lists.01.org
> Cc: Tian, Feng <feng.tian@intel.com>; Gao, Liming <liming.gao@intel.com>;
> Zeng, Star <star.zeng@intel.com>; Kinney, Michael D
> <michael.d.kinney@intel.com>; Fan, Jeff <jeff.fan@intel.com>; Zhang, Chao
> B <chao.b.zhang@intel.com>
> Subject: [edk2] [PATCH 00/45] Add capsule update and recovery sample.
> 
> This series patch provides sample on how to do signed capsule update
> and recovery in EDKII.
> 
> This series patch is also checked into git@github.com:jyao1/edk2.git.
> 
> The feature includes:
> 1) Define EDKII signed system BIOS capsule format.
> 2) Provide EDKII signed system BIOS update sample.
> 3) Provide EDKII signed recovery sample.
> 4) Provide Microcode update sample for X86 system.
> 5) Update Quark to use new capsule/recovery solution.
> 6) Update Vlv2(MinnowMax) to use new capsule/recovery solution.
> 
> The signed capsule/recovery solution is in MdeModulePkg.
> The capsule in IntelFrameworkModulePkg is deprecated.
> The Microcode update solution is in UefiCpuPkg.
> 
> Cc: Feng Tian <feng.tian@intel.com>
> Cc: Star Zeng <star.zeng@intel.com>
> Cc: Michael D Kinney <michael.d.kinney@intel.com>
> Cc: Liming Gao <liming.gao@intel.com>
> Cc: Chao Zhang <chao.b.zhang@intel.com>
> Cc: Jeff Fan <jeff.fan@intel.com>
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
> 
> 
> Jiewen Yao (45):
>   MdeModulePkg/Include: Add EDKII system FMP capsule header.
>   MdeModulePkg/Include: Add EdkiiSystemCapsuleLib definition.
>   MdeModulePkg/Include: Add FmpAuthenticationLib header.
>   MdeModulePkg/Include: Add IniParsingLib header.
>   MdeModulePkg/Include: Add PlatformFlashAccessLib header.
>   MdeModulePkg/CapsuleLib: Add ProcessCapsules() API.
>   MdeModulePkg/MdeModulePkg.dec: Add capsule related definition.
>   MdeModulePkg/IniParsingLib: Add InitParsingLib instance.
>   MdeModulePkg/FmpAuthenticationLib: Add FmpAuthenticationLib
> instance.
>   MdeModulePkg/DxeCapsuleLibFmp: Add DxeCapsuleLibFmp instance.
>   MdeModulePkg/DxeCapsuleLibNull: Add ProcessCapsules() interface.
>   MdeModulePkg/EdkiiSystemCapsuleLib: Add EdkiiSystemCapsuleLib
>     instance.
>   MdeModulePkg/PlatformFlashAccessLib: Add NULL
> PlatformFlashAccessLib.
>   MdeModulePkg/Esrt: Add ESRT_FW_TYPE_SYSTEMFIRMWARE check.
>   MdeModulePkg/SystemBiosUpdate: Add SystemBiosUpdate component.
>   MdeModulePkg/RecoveryModuleLoadPei: Add RecoveryModuleLoadPei.
>   MdeModulePkg/CapsuleApp: Add CapsuleApp application.
>   MdeModulePkg/MdeModulePkg.dsc: Add capsule related component.
>   IntelFrameworkModulePkg/DxeCapsuleLib: Add ProcessCapsules()
>     interface.
>   SecurityPkg/SecurityPkg.dec: Add PcdPkcs7CertBuffer PCD.
>   SecurityPkg/FmpAuthenticationPkcs7Lib: Add PKCS7 NULL class for FMP.
>   SecurityPkg/FmpAuthenticationRsa2048Sha256Lib: Add NULL class for
> FMP.
>   SecurityPkg/SecurityPkg.dsc: Add FmpAuthentication*Lib.
>   UefiCpuPkg/Include: Add Microcode FMP definition.
>   UefiCpuPkg/Include: Add MicrocodeFlashAccessLib header.
>   UefiCpuPkg/UefiCpuPkg.dec: Add Microcode capsule related definition.
>   UefiCpuPkg/MicrocodeUpdate: Add MicrocodeUpdate component.
>   UefiCpuPkg/MicrocodeFlashAccessLib: Add NULL
> MicrocodeFlashAccessLib.
>   UefiCpuPkg/MicrocodeCapsuleApp: Add MicrocodeCapsuleApp
> application.
>   UefiCpuPkg/UefiCpuPkg.dsc: Add MicrocodeCapsule related component.
>   QuarkPlatformPkg/PlatformFlashAccessLib: Add instance for capsule
>     update.
>   QuarkPlatformPkg/SystemBiosDescriptor: Add Descriptor for capsule
>     update.
>   QuarkPlatformPkg/SystemBiosUpdateConfig: Add capsule config file.
>   QuarkPlatformPkg/PlatformInit: Remove recovery PPI installation.
>   QuarkPlatformPkg/PlatformBootManager: Add capsule/recovery
> handling.
>   QuarkPlatformPkg/dsc/fdf: Add capsule/recovery support.
>   QuarkPlatformPkg/dsc/fdf: add capsule generation DSC/FDF.
>   Vlv2TbltDevicePkg/PlatformFlashAccessLib: Add instance for capsule
>     update.
>   Vlv2TbltDevicePkg/SystemBiosDescriptor: Add Descriptor for capsule
>     update.
>   Vlv2TbltDevicePkg/SystemBiosUpdateConfig: Add capsule config file.
>   Vlv2TbltDevicePkg/FlashDeviceLib: Add DXE flash device lib.
>   Vlv2TbltDevicePkg/PlatformBootManager: Add capsule/recovery
> handling.
>   Vlv2TbltDevicePkg/dsc/fdf: Add capsule/recovery support.
>   Vlv2TbltDevicePkg/dsc/fdf: add capsule generation DSC/FDF.
>   Vlv2TbltDevicePkg/bat: add capsule generation in bat.
> 
>  IntelFrameworkModulePkg/Library/DxeCapsuleLib/DxeCapsuleLib.c
> |   39 +-
>  MdeModulePkg/Application/CapsuleApp/AppSupport.c
> |  480 ++++++
>  MdeModulePkg/Application/CapsuleApp/CapsuleApp.c
> | 1047 +++++++++++++
>  MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf
> |   71 +
>  MdeModulePkg/Application/CapsuleApp/CapsuleApp.uni
> |   22 +
>  MdeModulePkg/Application/CapsuleApp/CapsuleAppExtra.uni
> |   19 +
>  MdeModulePkg/Application/CapsuleApp/CapsuleDump.c
> |  840 +++++++++++
>  MdeModulePkg/Include/Guid/EdkiiSystemFmpCapsule.h
> |  110 ++
>  MdeModulePkg/Include/Library/CapsuleLib.h
> |   45 +-
>  MdeModulePkg/Include/Library/EdkiiSystemCapsuleLib.h
> |  152 ++
>  MdeModulePkg/Include/Library/FmpAuthenticationLib.h
> |   91 ++
>  MdeModulePkg/Include/Library/IniParsingLib.h
> |  153 ++
>  MdeModulePkg/Include/Library/PlatformFlashAccessLib.h
> |   59 +
>  MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.c
> | 1538 ++++++++++++++++++++
>  MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.inf
> |   82 ++
>  MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.uni
> |   22 +
>  MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleProcessLib.c
> |  517 +++++++
>  MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleReportLib.c
> |  447 ++++++
>  MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleRuntime.c
> |  112 ++
>  MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf
> |   85 ++
>  MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.uni
> |   22 +
>  MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.c
> |   47 +-
>  MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.c
> |  609 ++++++++
>  MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.inf
> |   55 +
>  MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.uni
> |   22 +
>  MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.c
> |  274 ++++
>  MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.inf
> |   47 +
>  MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.uni
> |   22 +
>  MdeModulePkg/Library/IniParsingLib/IniParsingLib.c
> | 1053 ++++++++++++++
>  MdeModulePkg/Library/IniParsingLib/IniParsingLib.inf
> |   42 +
>  MdeModulePkg/Library/IniParsingLib/IniParsingLib.uni
> |   22 +
> 
> MdeModulePkg/Library/PlatformFlashAccessLibNull/PlatformFlashAccessLib
> Null.c                  |   54 +
> 
> MdeModulePkg/Library/PlatformFlashAccessLibNull/PlatformFlashAccessLib
> Null.inf                |   40 +
> 
> MdeModulePkg/Library/PlatformFlashAccessLibNull/PlatformFlashAccessLib
> Null.uni                |   21 +
>  MdeModulePkg/MdeModulePkg.dec
> |  106 ++
>  MdeModulePkg/MdeModulePkg.dsc
> |   24 +
>  MdeModulePkg/Universal/EsrtDxe/EsrtDxe.inf
> |    3 +-
>  MdeModulePkg/Universal/EsrtDxe/EsrtImpl.c
> |   37 +-
>  MdeModulePkg/Universal/RecoveryModuleLoadPei/ParseConfigProfile.c
> |  158 ++
> 
> MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadP
> ei.c                          |  746 ++++++++++
> 
> MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadP
> ei.h                          |   44 +
> 
> MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadP
> ei.inf                        |   71 +
> 
> MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadP
> ei.uni                        |   21 +
> 
> MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadP
> eiExtra.uni                   |   20 +
>  MdeModulePkg/Universal/SystemBiosUpdate/ParseConfigProfile.c
> |  219 +++
>  MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosDxe.h
> |  393 +++++
>  MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosMainDxe.c
> |  484 ++++++
>  MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosMainSetImage.c
> |  453 ++++++
> 
> MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosMainSetImageDu
> mmy.c                         |   90 ++
>  MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxe.inf
> |   66 +
>  MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxe.uni
> |   21 +
> 
> MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxeExtra.u
> ni                          |   20 +
>  MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxe.inf
> |   70 +
>  MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxe.uni
> |   21 +
> 
> MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxeExtra.u
> ni                          |   20 +
> 
> QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/Platfor
> mFlashAccessLibDxe.c   |  200 +++
> 
> QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/Platfor
> mFlashAccessLibDxe.inf |   52 +
> 
> QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/SpiFlas
> hDevice.c              |  336 +++++
> 
> QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/SpiFlas
> hDevice.h              |  186 +++
> 
> QuarkPlatformPkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescr
> iptor.aslc               |   88 ++
> 
> QuarkPlatformPkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescr
> iptor.inf                |   45 +
> 
> QuarkPlatformPkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescr
> iptorPei.c               |   66 +
> 
> QuarkPlatformPkg/Feature/Capsule/SystemBiosUpdateConfig/SystemBiosU
> pdateConfig.ini            |   62 +
> 
> QuarkPlatformPkg/Library/PlatformBootManagerLib/PlatformBootManager
> .c                         |   95 +-
> 
> QuarkPlatformPkg/Library/PlatformBootManagerLib/PlatformBootManager
> .h                         |    8 +-
> 
> QuarkPlatformPkg/Library/PlatformBootManagerLib/PlatformBootManager
> Lib.inf                    |    8 +-
>  QuarkPlatformPkg/Platform/Pei/PlatformInit/MemoryCallback.c
> |    3 +-
>  QuarkPlatformPkg/Quark.dsc
> |   61 +-
>  QuarkPlatformPkg/Quark.fdf
> |   53 +
>  QuarkPlatformPkg/QuarkCapsule.dsc
> |   44 +
>  QuarkPlatformPkg/QuarkCapsule.fdf
> |   82 ++
>  QuarkPlatformPkg/QuarkMin.dsc
> |    7 +-
> 
> SecurityPkg/Library/FmpAuthenticationPkcs7Lib/FmpAuthenticationPkcs7Lib
> .c                     |  144 ++
> 
> SecurityPkg/Library/FmpAuthenticationPkcs7Lib/FmpAuthenticationPkcs7Lib
> .inf                   |   52 +
> 
> SecurityPkg/Library/FmpAuthenticationPkcs7Lib/FmpAuthenticationPkcs7Lib
> .uni                   |   26 +
> 
> SecurityPkg/Library/FmpAuthenticationRsa2048Sha256Lib/FmpAuthenticatio
> nRsa2048Sha256Lib.c     |  286 ++++
> 
> SecurityPkg/Library/FmpAuthenticationRsa2048Sha256Lib/FmpAuthenticatio
> nRsa2048Sha256Lib.inf   |   53 +
> 
> SecurityPkg/Library/FmpAuthenticationRsa2048Sha256Lib/FmpAuthenticatio
> nRsa2048Sha256Lib.uni   |   26 +
>  SecurityPkg/SecurityPkg.dec
> |    6 +
>  SecurityPkg/SecurityPkg.dsc
> |    3 +
>  UefiCpuPkg/Application/MicrocodeCapsuleApp/AppSupport.c
> |  480 ++++++
>  UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.c
> |  283 ++++
>  UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.inf
> |   62 +
>  UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.uni
> |   22 +
> 
> UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleAppExtra.
> uni                       |   19 +
>  UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleDump.c
> |  171 +++
>  UefiCpuPkg/Include/Guid/MicrocodeFmp.h
> |   21 +
>  UefiCpuPkg/Include/Library/MicrocodeFlashAccessLib.h
> |   39 +
> 
> UefiCpuPkg/Library/MicrocodeFlashAccessLibNull/MicrocodeFlashAccessLib
> Null.c                  |   42 +
> 
> UefiCpuPkg/Library/MicrocodeFlashAccessLibNull/MicrocodeFlashAccessLib
> Null.inf                |   40 +
> 
> UefiCpuPkg/Library/MicrocodeFlashAccessLibNull/MicrocodeFlashAccessLib
> Null.uni                |   21 +
>  UefiCpuPkg/MicrocodeUpdate/MicrocodeFmp.c
> |  641 ++++++++
>  UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.c
> |  775 ++++++++++
>  UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.h
> |  299 ++++
>  UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.inf
> |   68 +
>  UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdateDxe.uni
> |   21 +
>  UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdateDxeExtra.uni
> |   20 +
>  UefiCpuPkg/UefiCpuPkg.dec
> |    7 +
>  UefiCpuPkg/UefiCpuPkg.dsc
> |    3 +
> 
> Vlv2TbltDevicePkg/Feature/Capsule/Library/PlatformFlashAccessLib/Platfor
> mFlashAccessLib.c     |  192 +++
> 
> Vlv2TbltDevicePkg/Feature/Capsule/Library/PlatformFlashAccessLib/Platfor
> mFlashAccessLib.inf   |   47 +
> 
> Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescr
> iptor.aslc              |   86 ++
> 
> Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescr
> iptor.inf               |   45 +
> 
> Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescr
> iptorPei.c              |   66 +
> 
> Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosUpdateConfig/SystemBiosU
> pdateConfig.ini           |   72 +
> 
> Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosUpdateConfig/SystemBiosU
> pdateConfigGcc.ini        |   72 +
>  Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLib.c
> |  156 +-
>  Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLib.inf
> |    8 +-
>  Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLibDxe.c
> |   62 +
>  Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLibDxe.inf
> |   49 +
> 
> Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLibDxeRuntimeSmm.c
> |  188 +++
>  Vlv2TbltDevicePkg/Library/FlashDeviceLib/SpiChipDefinitions.h
> |    5 +-
>  Vlv2TbltDevicePkg/Library/PlatformBdsLib/BdsPlatform.c
> |  117 +-
>  Vlv2TbltDevicePkg/Library/PlatformBdsLib/PlatformBdsLib.inf
> |    2 +
>  Vlv2TbltDevicePkg/PlatformCapsule.dsc
> |   44 +
>  Vlv2TbltDevicePkg/PlatformCapsule.fdf
> |   81 ++
>  Vlv2TbltDevicePkg/PlatformCapsuleGcc.fdf
> |   81 ++
>  Vlv2TbltDevicePkg/PlatformPkg.fdf
> |  132 +-
>  Vlv2TbltDevicePkg/PlatformPkgConfig.dsc
> |    3 +-
>  Vlv2TbltDevicePkg/PlatformPkgGcc.fdf
> |  132 +-
>  Vlv2TbltDevicePkg/PlatformPkgGccX64.dsc
> |   70 +-
>  Vlv2TbltDevicePkg/PlatformPkgIA32.dsc
> |   70 +-
>  Vlv2TbltDevicePkg/PlatformPkgX64.dsc
> |   70 +-
>  Vlv2TbltDevicePkg/bld_vlv.bat
> |    8 +-
>  124 files changed, 17848 insertions(+), 384 deletions(-)
>  create mode 100644
> MdeModulePkg/Application/CapsuleApp/AppSupport.c
>  create mode 100644
> MdeModulePkg/Application/CapsuleApp/CapsuleApp.c
>  create mode 100644
> MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf
>  create mode 100644
> MdeModulePkg/Application/CapsuleApp/CapsuleApp.uni
>  create mode 100644
> MdeModulePkg/Application/CapsuleApp/CapsuleAppExtra.uni
>  create mode 100644
> MdeModulePkg/Application/CapsuleApp/CapsuleDump.c
>  create mode 100644
> MdeModulePkg/Include/Guid/EdkiiSystemFmpCapsule.h
>  create mode 100644
> MdeModulePkg/Include/Library/EdkiiSystemCapsuleLib.h
>  create mode 100644
> MdeModulePkg/Include/Library/FmpAuthenticationLib.h
>  create mode 100644 MdeModulePkg/Include/Library/IniParsingLib.h
>  create mode 100644
> MdeModulePkg/Include/Library/PlatformFlashAccessLib.h
>  create mode 100644
> MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.c
>  create mode 100644
> MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.inf
>  create mode 100644
> MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.uni
>  create mode 100644
> MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleProcessLib.c
>  create mode 100644
> MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleReportLib.c
>  create mode 100644
> MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleRuntime.c
>  create mode 100644
> MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf
>  create mode 100644
> MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.uni
>  create mode 100644
> MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.c
>  create mode 100644
> MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.inf
>  create mode 100644
> MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.uni
>  create mode 100644
> MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.c
>  create mode 100644
> MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.inf
>  create mode 100644
> MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.uni
>  create mode 100644 MdeModulePkg/Library/IniParsingLib/IniParsingLib.c
>  create mode 100644 MdeModulePkg/Library/IniParsingLib/IniParsingLib.inf
>  create mode 100644
> MdeModulePkg/Library/IniParsingLib/IniParsingLib.uni
>  create mode 100644
> MdeModulePkg/Library/PlatformFlashAccessLibNull/PlatformFlashAccessLib
> Null.c
>  create mode 100644
> MdeModulePkg/Library/PlatformFlashAccessLibNull/PlatformFlashAccessLib
> Null.inf
>  create mode 100644
> MdeModulePkg/Library/PlatformFlashAccessLibNull/PlatformFlashAccessLib
> Null.uni
>  create mode 100644
> MdeModulePkg/Universal/RecoveryModuleLoadPei/ParseConfigProfile.c
>  create mode 100644
> MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadP
> ei.c
>  create mode 100644
> MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadP
> ei.h
>  create mode 100644
> MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadP
> ei.inf
>  create mode 100644
> MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadP
> ei.uni
>  create mode 100644
> MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadP
> eiExtra.uni
>  create mode 100644
> MdeModulePkg/Universal/SystemBiosUpdate/ParseConfigProfile.c
>  create mode 100644
> MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosDxe.h
>  create mode 100644
> MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosMainDxe.c
>  create mode 100644
> MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosMainSetImage.c
>  create mode 100644
> MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosMainSetImageDu
> mmy.c
>  create mode 100644
> MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxe.inf
>  create mode 100644
> MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxe.uni
>  create mode 100644
> MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxeExtra.u
> ni
>  create mode 100644
> MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxe.inf
>  create mode 100644
> MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxe.uni
>  create mode 100644
> MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxeExtra.u
> ni
>  create mode 100644
> QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/Platfor
> mFlashAccessLibDxe.c
>  create mode 100644
> QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/Platfor
> mFlashAccessLibDxe.inf
>  create mode 100644
> QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/SpiFlas
> hDevice.c
>  create mode 100644
> QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/SpiFlas
> hDevice.h
>  create mode 100644
> QuarkPlatformPkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescr
> iptor.aslc
>  create mode 100644
> QuarkPlatformPkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescr
> iptor.inf
>  create mode 100644
> QuarkPlatformPkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescr
> iptorPei.c
>  create mode 100644
> QuarkPlatformPkg/Feature/Capsule/SystemBiosUpdateConfig/SystemBiosU
> pdateConfig.ini
>  create mode 100644 QuarkPlatformPkg/QuarkCapsule.dsc
>  create mode 100644 QuarkPlatformPkg/QuarkCapsule.fdf
>  create mode 100644
> SecurityPkg/Library/FmpAuthenticationPkcs7Lib/FmpAuthenticationPkcs7Lib
> .c
>  create mode 100644
> SecurityPkg/Library/FmpAuthenticationPkcs7Lib/FmpAuthenticationPkcs7Lib
> .inf
>  create mode 100644
> SecurityPkg/Library/FmpAuthenticationPkcs7Lib/FmpAuthenticationPkcs7Lib
> .uni
>  create mode 100644
> SecurityPkg/Library/FmpAuthenticationRsa2048Sha256Lib/FmpAuthenticatio
> nRsa2048Sha256Lib.c
>  create mode 100644
> SecurityPkg/Library/FmpAuthenticationRsa2048Sha256Lib/FmpAuthenticatio
> nRsa2048Sha256Lib.inf
>  create mode 100644
> SecurityPkg/Library/FmpAuthenticationRsa2048Sha256Lib/FmpAuthenticatio
> nRsa2048Sha256Lib.uni
>  create mode 100644
> UefiCpuPkg/Application/MicrocodeCapsuleApp/AppSupport.c
>  create mode 100644
> UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.c
>  create mode 100644
> UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.inf
>  create mode 100644
> UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.uni
>  create mode 100644
> UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleAppExtra.
> uni
>  create mode 100644
> UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleDump.c
>  create mode 100644 UefiCpuPkg/Include/Guid/MicrocodeFmp.h
>  create mode 100644
> UefiCpuPkg/Include/Library/MicrocodeFlashAccessLib.h
>  create mode 100644
> UefiCpuPkg/Library/MicrocodeFlashAccessLibNull/MicrocodeFlashAccessLib
> Null.c
>  create mode 100644
> UefiCpuPkg/Library/MicrocodeFlashAccessLibNull/MicrocodeFlashAccessLib
> Null.inf
>  create mode 100644
> UefiCpuPkg/Library/MicrocodeFlashAccessLibNull/MicrocodeFlashAccessLib
> Null.uni
>  create mode 100644 UefiCpuPkg/MicrocodeUpdate/MicrocodeFmp.c
>  create mode 100644 UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.c
>  create mode 100644 UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.h
>  create mode 100644 UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.inf
>  create mode 100644
> UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdateDxe.uni
>  create mode 100644
> UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdateDxeExtra.uni
>  create mode 100644
> Vlv2TbltDevicePkg/Feature/Capsule/Library/PlatformFlashAccessLib/Platfor
> mFlashAccessLib.c
>  create mode 100644
> Vlv2TbltDevicePkg/Feature/Capsule/Library/PlatformFlashAccessLib/Platfor
> mFlashAccessLib.inf
>  create mode 100644
> Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescr
> iptor.aslc
>  create mode 100644
> Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescr
> iptor.inf
>  create mode 100644
> Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescr
> iptorPei.c
>  create mode 100644
> Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosUpdateConfig/SystemBiosU
> pdateConfig.ini
>  create mode 100644
> Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosUpdateConfig/SystemBiosU
> pdateConfigGcc.ini
>  create mode 100644
> Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLibDxe.c
>  create mode 100644
> Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLibDxe.inf
>  create mode 100644
> Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLibDxeRuntimeSmm.c
>  create mode 100644 Vlv2TbltDevicePkg/PlatformCapsule.dsc
>  create mode 100644 Vlv2TbltDevicePkg/PlatformCapsule.fdf
>  create mode 100644 Vlv2TbltDevicePkg/PlatformCapsuleGcc.fdf
> 
> --
> 2.7.4.windows.1
> 
> _______________________________________________
> edk2-devel mailing list
> edk2-devel@lists.01.org
> https://lists.01.org/mailman/listinfo/edk2-devel


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

* Re: [PATCH 19/45] IntelFrameworkModulePkg/DxeCapsuleLib: Add ProcessCapsules() interface.
  2016-09-21  6:45 ` [PATCH 19/45] IntelFrameworkModulePkg/DxeCapsuleLib: Add ProcessCapsules() interface Jiewen Yao
@ 2016-09-28  8:08   ` Fan, Jeff
  0 siblings, 0 replies; 83+ messages in thread
From: Fan, Jeff @ 2016-09-28  8:08 UTC (permalink / raw)
  To: Yao, Jiewen, edk2-devel@lists.01.org
  Cc: Tian, Feng, Zeng, Star, Kinney, Michael D, Gao, Liming,
	Zhang, Chao B


Reviewed-by: Jeff Fan <jeff.fan@intel.com>

-----Original Message-----
From: Yao, Jiewen 
Sent: Wednesday, September 21, 2016 2:45 PM
To: edk2-devel@lists.01.org
Cc: Fan, Jeff; Tian, Feng; Zeng, Star; Kinney, Michael D; Gao, Liming; Zhang, Chao B
Subject: [PATCH 19/45] IntelFrameworkModulePkg/DxeCapsuleLib: Add ProcessCapsules() interface.

Add NULL ProcessCapsules() interface for DxeCapsuleLib.
IntelFrameworkModulePkg is under maintenance phase.
We stop adding new feature there.
Just add NULL function to make it pass build.

Cc: Jeff Fan <jeff.fan@intel.com>
Cc: Feng Tian <feng.tian@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Chao Zhang <chao.b.zhang@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
---
 IntelFrameworkModulePkg/Library/DxeCapsuleLib/DxeCapsuleLib.c | 39 +++++++++++++++++++-
 1 file changed, 38 insertions(+), 1 deletion(-)

diff --git a/IntelFrameworkModulePkg/Library/DxeCapsuleLib/DxeCapsuleLib.c b/IntelFrameworkModulePkg/Library/DxeCapsuleLib/DxeCapsuleLib.c
index fc9b533..c964b2d 100644
--- a/IntelFrameworkModulePkg/Library/DxeCapsuleLib/DxeCapsuleLib.c
+++ b/IntelFrameworkModulePkg/Library/DxeCapsuleLib/DxeCapsuleLib.c
@@ -1,7 +1,7 @@
 /** @file
   Capsule Library instance to process capsule images.
 
-  Copyright (c) 2007 - 2013, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2007 - 2016, Intel Corporation. All rights 
+ reserved.<BR>
 
   This program and the accompanying materials
   are licensed and made available under the terms and conditions of the BSD License @@ -515,4 +515,41 @@ ProcessCapsuleImage (
   return Status;
 }
 
+/**
+
+  This routine is called to process capsules.
+
+  Caution: This function may receive untrusted input.
+
+  If the current boot mode is NOT BOOT_ON_FLASH_UPDATE, this routine does nothing.
+  If the current boot mode is BOOT_ON_FLASH_UPDATE, the capsules 
+ reported in  EFI_HOB_UEFI_CAPSULE are processed. If there is no 
+ EFI_HOB_UEFI_CAPSULE, this  routine does nothing.
+
+  This routine should be called twice in BDS.
+  1) The first call must be before EndOfDxe. The system capsules is processed.
+     If device capsule FMP protocols are exposted at this time and device FMP
+     capsule has zero EmbeddedDriverCount, the device capsules are processed.
+     Each individual capsule result is recorded in capsule record variable.
+     System may reset in this function, if reset is required by capsule.
+
+  2) The second call must be after EndOfDxe and after ConnectAll, so that all
+     device capsule FMP protocols are exposed.
+     The system capsules are skipped. If the device capsules are NOT processed
+     in first call, they are processed here.
+     Each individual capsule result is recorded in capsule record variable.
+     System may reset in this function, if reset is required by capsule.
+
+  @retval EFI_SUCCESS             There is no error when processing capsules.
+  @retval EFI_OUT_OF_RESOURCES    No enough resource to process capsules.
+
+**/
+EFI_STATUS
+EFIAPI
+ProcessCapsules(
+  VOID
+  )
+{
+  return EFI_UNSUPPORTED;
+}
 
--
2.7.4.windows.1



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

* Re: [PATCH 00/45] Add capsule update and recovery sample.
  2016-09-28  8:05 ` Yao, Jiewen
@ 2016-09-28 14:54   ` Kinney, Michael D
  0 siblings, 0 replies; 83+ messages in thread
From: Kinney, Michael D @ 2016-09-28 14:54 UTC (permalink / raw)
  To: Yao, Jiewen, edk2-devel@lists.01.org, Kinney, Michael D
  Cc: Tian, Feng, Gao, Liming, Zeng, Star, Fan, Jeff, Zhang, Chao B

Jiewen,

I will review the Quark specific changes today.

Mike

> -----Original Message-----
> From: Yao, Jiewen
> Sent: Wednesday, September 28, 2016 1:05 AM
> To: Yao, Jiewen <jiewen.yao@intel.com>; edk2-devel@lists.01.org
> Cc: Tian, Feng <feng.tian@intel.com>; Gao, Liming <liming.gao@intel.com>; Zeng, Star
> <star.zeng@intel.com>; Kinney, Michael D <michael.d.kinney@intel.com>; Fan, Jeff
> <jeff.fan@intel.com>; Zhang, Chao B <chao.b.zhang@intel.com>
> Subject: RE: [edk2] [PATCH 00/45] Add capsule update and recovery sample.
> 
> Hi
> I got reviewed-by for MdeModulePkg/SecurityPkg/UefiCpuPkg/Vlv2DevicePkg. Thanks each
> package owner.
> 
> I have not got reviewed-by for QuarkPlatformPkg yet. Can QuarkPlatformPkg owner review
> the platform update?
> Or it takes quark owner more time to review QuarkPlatformPkg, I will plan to check in
> above 4 reviewed package at first.
> 
> QuarkPlatformPkg update is independent and can be checked in and enabled later.
> 
> Thank you
> Yao Jiewen
> 
> 
> > -----Original Message-----
> > From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of
> > Jiewen Yao
> > Sent: Wednesday, September 21, 2016 2:45 PM
> > To: edk2-devel@lists.01.org
> > Cc: Tian, Feng <feng.tian@intel.com>; Gao, Liming <liming.gao@intel.com>;
> > Zeng, Star <star.zeng@intel.com>; Kinney, Michael D
> > <michael.d.kinney@intel.com>; Fan, Jeff <jeff.fan@intel.com>; Zhang, Chao
> > B <chao.b.zhang@intel.com>
> > Subject: [edk2] [PATCH 00/45] Add capsule update and recovery sample.
> >
> > This series patch provides sample on how to do signed capsule update
> > and recovery in EDKII.
> >
> > This series patch is also checked into git@github.com:jyao1/edk2.git.
> >
> > The feature includes:
> > 1) Define EDKII signed system BIOS capsule format.
> > 2) Provide EDKII signed system BIOS update sample.
> > 3) Provide EDKII signed recovery sample.
> > 4) Provide Microcode update sample for X86 system.
> > 5) Update Quark to use new capsule/recovery solution.
> > 6) Update Vlv2(MinnowMax) to use new capsule/recovery solution.
> >
> > The signed capsule/recovery solution is in MdeModulePkg.
> > The capsule in IntelFrameworkModulePkg is deprecated.
> > The Microcode update solution is in UefiCpuPkg.
> >
> > Cc: Feng Tian <feng.tian@intel.com>
> > Cc: Star Zeng <star.zeng@intel.com>
> > Cc: Michael D Kinney <michael.d.kinney@intel.com>
> > Cc: Liming Gao <liming.gao@intel.com>
> > Cc: Chao Zhang <chao.b.zhang@intel.com>
> > Cc: Jeff Fan <jeff.fan@intel.com>
> > Contributed-under: TianoCore Contribution Agreement 1.0
> > Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
> >
> >
> > Jiewen Yao (45):
> >   MdeModulePkg/Include: Add EDKII system FMP capsule header.
> >   MdeModulePkg/Include: Add EdkiiSystemCapsuleLib definition.
> >   MdeModulePkg/Include: Add FmpAuthenticationLib header.
> >   MdeModulePkg/Include: Add IniParsingLib header.
> >   MdeModulePkg/Include: Add PlatformFlashAccessLib header.
> >   MdeModulePkg/CapsuleLib: Add ProcessCapsules() API.
> >   MdeModulePkg/MdeModulePkg.dec: Add capsule related definition.
> >   MdeModulePkg/IniParsingLib: Add InitParsingLib instance.
> >   MdeModulePkg/FmpAuthenticationLib: Add FmpAuthenticationLib
> > instance.
> >   MdeModulePkg/DxeCapsuleLibFmp: Add DxeCapsuleLibFmp instance.
> >   MdeModulePkg/DxeCapsuleLibNull: Add ProcessCapsules() interface.
> >   MdeModulePkg/EdkiiSystemCapsuleLib: Add EdkiiSystemCapsuleLib
> >     instance.
> >   MdeModulePkg/PlatformFlashAccessLib: Add NULL
> > PlatformFlashAccessLib.
> >   MdeModulePkg/Esrt: Add ESRT_FW_TYPE_SYSTEMFIRMWARE check.
> >   MdeModulePkg/SystemBiosUpdate: Add SystemBiosUpdate component.
> >   MdeModulePkg/RecoveryModuleLoadPei: Add RecoveryModuleLoadPei.
> >   MdeModulePkg/CapsuleApp: Add CapsuleApp application.
> >   MdeModulePkg/MdeModulePkg.dsc: Add capsule related component.
> >   IntelFrameworkModulePkg/DxeCapsuleLib: Add ProcessCapsules()
> >     interface.
> >   SecurityPkg/SecurityPkg.dec: Add PcdPkcs7CertBuffer PCD.
> >   SecurityPkg/FmpAuthenticationPkcs7Lib: Add PKCS7 NULL class for FMP.
> >   SecurityPkg/FmpAuthenticationRsa2048Sha256Lib: Add NULL class for
> > FMP.
> >   SecurityPkg/SecurityPkg.dsc: Add FmpAuthentication*Lib.
> >   UefiCpuPkg/Include: Add Microcode FMP definition.
> >   UefiCpuPkg/Include: Add MicrocodeFlashAccessLib header.
> >   UefiCpuPkg/UefiCpuPkg.dec: Add Microcode capsule related definition.
> >   UefiCpuPkg/MicrocodeUpdate: Add MicrocodeUpdate component.
> >   UefiCpuPkg/MicrocodeFlashAccessLib: Add NULL
> > MicrocodeFlashAccessLib.
> >   UefiCpuPkg/MicrocodeCapsuleApp: Add MicrocodeCapsuleApp
> > application.
> >   UefiCpuPkg/UefiCpuPkg.dsc: Add MicrocodeCapsule related component.
> >   QuarkPlatformPkg/PlatformFlashAccessLib: Add instance for capsule
> >     update.
> >   QuarkPlatformPkg/SystemBiosDescriptor: Add Descriptor for capsule
> >     update.
> >   QuarkPlatformPkg/SystemBiosUpdateConfig: Add capsule config file.
> >   QuarkPlatformPkg/PlatformInit: Remove recovery PPI installation.
> >   QuarkPlatformPkg/PlatformBootManager: Add capsule/recovery
> > handling.
> >   QuarkPlatformPkg/dsc/fdf: Add capsule/recovery support.
> >   QuarkPlatformPkg/dsc/fdf: add capsule generation DSC/FDF.
> >   Vlv2TbltDevicePkg/PlatformFlashAccessLib: Add instance for capsule
> >     update.
> >   Vlv2TbltDevicePkg/SystemBiosDescriptor: Add Descriptor for capsule
> >     update.
> >   Vlv2TbltDevicePkg/SystemBiosUpdateConfig: Add capsule config file.
> >   Vlv2TbltDevicePkg/FlashDeviceLib: Add DXE flash device lib.
> >   Vlv2TbltDevicePkg/PlatformBootManager: Add capsule/recovery
> > handling.
> >   Vlv2TbltDevicePkg/dsc/fdf: Add capsule/recovery support.
> >   Vlv2TbltDevicePkg/dsc/fdf: add capsule generation DSC/FDF.
> >   Vlv2TbltDevicePkg/bat: add capsule generation in bat.
> >
> >  IntelFrameworkModulePkg/Library/DxeCapsuleLib/DxeCapsuleLib.c
> > |   39 +-
> >  MdeModulePkg/Application/CapsuleApp/AppSupport.c
> > |  480 ++++++
> >  MdeModulePkg/Application/CapsuleApp/CapsuleApp.c
> > | 1047 +++++++++++++
> >  MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf
> > |   71 +
> >  MdeModulePkg/Application/CapsuleApp/CapsuleApp.uni
> > |   22 +
> >  MdeModulePkg/Application/CapsuleApp/CapsuleAppExtra.uni
> > |   19 +
> >  MdeModulePkg/Application/CapsuleApp/CapsuleDump.c
> > |  840 +++++++++++
> >  MdeModulePkg/Include/Guid/EdkiiSystemFmpCapsule.h
> > |  110 ++
> >  MdeModulePkg/Include/Library/CapsuleLib.h
> > |   45 +-
> >  MdeModulePkg/Include/Library/EdkiiSystemCapsuleLib.h
> > |  152 ++
> >  MdeModulePkg/Include/Library/FmpAuthenticationLib.h
> > |   91 ++
> >  MdeModulePkg/Include/Library/IniParsingLib.h
> > |  153 ++
> >  MdeModulePkg/Include/Library/PlatformFlashAccessLib.h
> > |   59 +
> >  MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.c
> > | 1538 ++++++++++++++++++++
> >  MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.inf
> > |   82 ++
> >  MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.uni
> > |   22 +
> >  MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleProcessLib.c
> > |  517 +++++++
> >  MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleReportLib.c
> > |  447 ++++++
> >  MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleRuntime.c
> > |  112 ++
> >  MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf
> > |   85 ++
> >  MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.uni
> > |   22 +
> >  MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.c
> > |   47 +-
> >  MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.c
> > |  609 ++++++++
> >  MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.inf
> > |   55 +
> >  MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.uni
> > |   22 +
> >  MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.c
> > |  274 ++++
> >  MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.inf
> > |   47 +
> >  MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.uni
> > |   22 +
> >  MdeModulePkg/Library/IniParsingLib/IniParsingLib.c
> > | 1053 ++++++++++++++
> >  MdeModulePkg/Library/IniParsingLib/IniParsingLib.inf
> > |   42 +
> >  MdeModulePkg/Library/IniParsingLib/IniParsingLib.uni
> > |   22 +
> >
> > MdeModulePkg/Library/PlatformFlashAccessLibNull/PlatformFlashAccessLib
> > Null.c                  |   54 +
> >
> > MdeModulePkg/Library/PlatformFlashAccessLibNull/PlatformFlashAccessLib
> > Null.inf                |   40 +
> >
> > MdeModulePkg/Library/PlatformFlashAccessLibNull/PlatformFlashAccessLib
> > Null.uni                |   21 +
> >  MdeModulePkg/MdeModulePkg.dec
> > |  106 ++
> >  MdeModulePkg/MdeModulePkg.dsc
> > |   24 +
> >  MdeModulePkg/Universal/EsrtDxe/EsrtDxe.inf
> > |    3 +-
> >  MdeModulePkg/Universal/EsrtDxe/EsrtImpl.c
> > |   37 +-
> >  MdeModulePkg/Universal/RecoveryModuleLoadPei/ParseConfigProfile.c
> > |  158 ++
> >
> > MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadP
> > ei.c                          |  746 ++++++++++
> >
> > MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadP
> > ei.h                          |   44 +
> >
> > MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadP
> > ei.inf                        |   71 +
> >
> > MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadP
> > ei.uni                        |   21 +
> >
> > MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadP
> > eiExtra.uni                   |   20 +
> >  MdeModulePkg/Universal/SystemBiosUpdate/ParseConfigProfile.c
> > |  219 +++
> >  MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosDxe.h
> > |  393 +++++
> >  MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosMainDxe.c
> > |  484 ++++++
> >  MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosMainSetImage.c
> > |  453 ++++++
> >
> > MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosMainSetImageDu
> > mmy.c                         |   90 ++
> >  MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxe.inf
> > |   66 +
> >  MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxe.uni
> > |   21 +
> >
> > MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxeExtra.u
> > ni                          |   20 +
> >  MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxe.inf
> > |   70 +
> >  MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxe.uni
> > |   21 +
> >
> > MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxeExtra.u
> > ni                          |   20 +
> >
> > QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/Platfor
> > mFlashAccessLibDxe.c   |  200 +++
> >
> > QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/Platfor
> > mFlashAccessLibDxe.inf |   52 +
> >
> > QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/SpiFlas
> > hDevice.c              |  336 +++++
> >
> > QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/SpiFlas
> > hDevice.h              |  186 +++
> >
> > QuarkPlatformPkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescr
> > iptor.aslc               |   88 ++
> >
> > QuarkPlatformPkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescr
> > iptor.inf                |   45 +
> >
> > QuarkPlatformPkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescr
> > iptorPei.c               |   66 +
> >
> > QuarkPlatformPkg/Feature/Capsule/SystemBiosUpdateConfig/SystemBiosU
> > pdateConfig.ini            |   62 +
> >
> > QuarkPlatformPkg/Library/PlatformBootManagerLib/PlatformBootManager
> > .c                         |   95 +-
> >
> > QuarkPlatformPkg/Library/PlatformBootManagerLib/PlatformBootManager
> > .h                         |    8 +-
> >
> > QuarkPlatformPkg/Library/PlatformBootManagerLib/PlatformBootManager
> > Lib.inf                    |    8 +-
> >  QuarkPlatformPkg/Platform/Pei/PlatformInit/MemoryCallback.c
> > |    3 +-
> >  QuarkPlatformPkg/Quark.dsc
> > |   61 +-
> >  QuarkPlatformPkg/Quark.fdf
> > |   53 +
> >  QuarkPlatformPkg/QuarkCapsule.dsc
> > |   44 +
> >  QuarkPlatformPkg/QuarkCapsule.fdf
> > |   82 ++
> >  QuarkPlatformPkg/QuarkMin.dsc
> > |    7 +-
> >
> > SecurityPkg/Library/FmpAuthenticationPkcs7Lib/FmpAuthenticationPkcs7Lib
> > .c                     |  144 ++
> >
> > SecurityPkg/Library/FmpAuthenticationPkcs7Lib/FmpAuthenticationPkcs7Lib
> > .inf                   |   52 +
> >
> > SecurityPkg/Library/FmpAuthenticationPkcs7Lib/FmpAuthenticationPkcs7Lib
> > .uni                   |   26 +
> >
> > SecurityPkg/Library/FmpAuthenticationRsa2048Sha256Lib/FmpAuthenticatio
> > nRsa2048Sha256Lib.c     |  286 ++++
> >
> > SecurityPkg/Library/FmpAuthenticationRsa2048Sha256Lib/FmpAuthenticatio
> > nRsa2048Sha256Lib.inf   |   53 +
> >
> > SecurityPkg/Library/FmpAuthenticationRsa2048Sha256Lib/FmpAuthenticatio
> > nRsa2048Sha256Lib.uni   |   26 +
> >  SecurityPkg/SecurityPkg.dec
> > |    6 +
> >  SecurityPkg/SecurityPkg.dsc
> > |    3 +
> >  UefiCpuPkg/Application/MicrocodeCapsuleApp/AppSupport.c
> > |  480 ++++++
> >  UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.c
> > |  283 ++++
> >  UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.inf
> > |   62 +
> >  UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.uni
> > |   22 +
> >
> > UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleAppExtra.
> > uni                       |   19 +
> >  UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleDump.c
> > |  171 +++
> >  UefiCpuPkg/Include/Guid/MicrocodeFmp.h
> > |   21 +
> >  UefiCpuPkg/Include/Library/MicrocodeFlashAccessLib.h
> > |   39 +
> >
> > UefiCpuPkg/Library/MicrocodeFlashAccessLibNull/MicrocodeFlashAccessLib
> > Null.c                  |   42 +
> >
> > UefiCpuPkg/Library/MicrocodeFlashAccessLibNull/MicrocodeFlashAccessLib
> > Null.inf                |   40 +
> >
> > UefiCpuPkg/Library/MicrocodeFlashAccessLibNull/MicrocodeFlashAccessLib
> > Null.uni                |   21 +
> >  UefiCpuPkg/MicrocodeUpdate/MicrocodeFmp.c
> > |  641 ++++++++
> >  UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.c
> > |  775 ++++++++++
> >  UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.h
> > |  299 ++++
> >  UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.inf
> > |   68 +
> >  UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdateDxe.uni
> > |   21 +
> >  UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdateDxeExtra.uni
> > |   20 +
> >  UefiCpuPkg/UefiCpuPkg.dec
> > |    7 +
> >  UefiCpuPkg/UefiCpuPkg.dsc
> > |    3 +
> >
> > Vlv2TbltDevicePkg/Feature/Capsule/Library/PlatformFlashAccessLib/Platfor
> > mFlashAccessLib.c     |  192 +++
> >
> > Vlv2TbltDevicePkg/Feature/Capsule/Library/PlatformFlashAccessLib/Platfor
> > mFlashAccessLib.inf   |   47 +
> >
> > Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescr
> > iptor.aslc              |   86 ++
> >
> > Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescr
> > iptor.inf               |   45 +
> >
> > Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescr
> > iptorPei.c              |   66 +
> >
> > Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosUpdateConfig/SystemBiosU
> > pdateConfig.ini           |   72 +
> >
> > Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosUpdateConfig/SystemBiosU
> > pdateConfigGcc.ini        |   72 +
> >  Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLib.c
> > |  156 +-
> >  Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLib.inf
> > |    8 +-
> >  Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLibDxe.c
> > |   62 +
> >  Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLibDxe.inf
> > |   49 +
> >
> > Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLibDxeRuntimeSmm.c
> > |  188 +++
> >  Vlv2TbltDevicePkg/Library/FlashDeviceLib/SpiChipDefinitions.h
> > |    5 +-
> >  Vlv2TbltDevicePkg/Library/PlatformBdsLib/BdsPlatform.c
> > |  117 +-
> >  Vlv2TbltDevicePkg/Library/PlatformBdsLib/PlatformBdsLib.inf
> > |    2 +
> >  Vlv2TbltDevicePkg/PlatformCapsule.dsc
> > |   44 +
> >  Vlv2TbltDevicePkg/PlatformCapsule.fdf
> > |   81 ++
> >  Vlv2TbltDevicePkg/PlatformCapsuleGcc.fdf
> > |   81 ++
> >  Vlv2TbltDevicePkg/PlatformPkg.fdf
> > |  132 +-
> >  Vlv2TbltDevicePkg/PlatformPkgConfig.dsc
> > |    3 +-
> >  Vlv2TbltDevicePkg/PlatformPkgGcc.fdf
> > |  132 +-
> >  Vlv2TbltDevicePkg/PlatformPkgGccX64.dsc
> > |   70 +-
> >  Vlv2TbltDevicePkg/PlatformPkgIA32.dsc
> > |   70 +-
> >  Vlv2TbltDevicePkg/PlatformPkgX64.dsc
> > |   70 +-
> >  Vlv2TbltDevicePkg/bld_vlv.bat
> > |    8 +-
> >  124 files changed, 17848 insertions(+), 384 deletions(-)
> >  create mode 100644
> > MdeModulePkg/Application/CapsuleApp/AppSupport.c
> >  create mode 100644
> > MdeModulePkg/Application/CapsuleApp/CapsuleApp.c
> >  create mode 100644
> > MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf
> >  create mode 100644
> > MdeModulePkg/Application/CapsuleApp/CapsuleApp.uni
> >  create mode 100644
> > MdeModulePkg/Application/CapsuleApp/CapsuleAppExtra.uni
> >  create mode 100644
> > MdeModulePkg/Application/CapsuleApp/CapsuleDump.c
> >  create mode 100644
> > MdeModulePkg/Include/Guid/EdkiiSystemFmpCapsule.h
> >  create mode 100644
> > MdeModulePkg/Include/Library/EdkiiSystemCapsuleLib.h
> >  create mode 100644
> > MdeModulePkg/Include/Library/FmpAuthenticationLib.h
> >  create mode 100644 MdeModulePkg/Include/Library/IniParsingLib.h
> >  create mode 100644
> > MdeModulePkg/Include/Library/PlatformFlashAccessLib.h
> >  create mode 100644
> > MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.c
> >  create mode 100644
> > MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.inf
> >  create mode 100644
> > MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.uni
> >  create mode 100644
> > MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleProcessLib.c
> >  create mode 100644
> > MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleReportLib.c
> >  create mode 100644
> > MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleRuntime.c
> >  create mode 100644
> > MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf
> >  create mode 100644
> > MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.uni
> >  create mode 100644
> > MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.c
> >  create mode 100644
> > MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.inf
> >  create mode 100644
> > MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.uni
> >  create mode 100644
> > MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.c
> >  create mode 100644
> > MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.inf
> >  create mode 100644
> > MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.uni
> >  create mode 100644 MdeModulePkg/Library/IniParsingLib/IniParsingLib.c
> >  create mode 100644 MdeModulePkg/Library/IniParsingLib/IniParsingLib.inf
> >  create mode 100644
> > MdeModulePkg/Library/IniParsingLib/IniParsingLib.uni
> >  create mode 100644
> > MdeModulePkg/Library/PlatformFlashAccessLibNull/PlatformFlashAccessLib
> > Null.c
> >  create mode 100644
> > MdeModulePkg/Library/PlatformFlashAccessLibNull/PlatformFlashAccessLib
> > Null.inf
> >  create mode 100644
> > MdeModulePkg/Library/PlatformFlashAccessLibNull/PlatformFlashAccessLib
> > Null.uni
> >  create mode 100644
> > MdeModulePkg/Universal/RecoveryModuleLoadPei/ParseConfigProfile.c
> >  create mode 100644
> > MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadP
> > ei.c
> >  create mode 100644
> > MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadP
> > ei.h
> >  create mode 100644
> > MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadP
> > ei.inf
> >  create mode 100644
> > MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadP
> > ei.uni
> >  create mode 100644
> > MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadP
> > eiExtra.uni
> >  create mode 100644
> > MdeModulePkg/Universal/SystemBiosUpdate/ParseConfigProfile.c
> >  create mode 100644
> > MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosDxe.h
> >  create mode 100644
> > MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosMainDxe.c
> >  create mode 100644
> > MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosMainSetImage.c
> >  create mode 100644
> > MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosMainSetImageDu
> > mmy.c
> >  create mode 100644
> > MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxe.inf
> >  create mode 100644
> > MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxe.uni
> >  create mode 100644
> > MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxeExtra.u
> > ni
> >  create mode 100644
> > MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxe.inf
> >  create mode 100644
> > MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxe.uni
> >  create mode 100644
> > MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxeExtra.u
> > ni
> >  create mode 100644
> > QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/Platfor
> > mFlashAccessLibDxe.c
> >  create mode 100644
> > QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/Platfor
> > mFlashAccessLibDxe.inf
> >  create mode 100644
> > QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/SpiFlas
> > hDevice.c
> >  create mode 100644
> > QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/SpiFlas
> > hDevice.h
> >  create mode 100644
> > QuarkPlatformPkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescr
> > iptor.aslc
> >  create mode 100644
> > QuarkPlatformPkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescr
> > iptor.inf
> >  create mode 100644
> > QuarkPlatformPkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescr
> > iptorPei.c
> >  create mode 100644
> > QuarkPlatformPkg/Feature/Capsule/SystemBiosUpdateConfig/SystemBiosU
> > pdateConfig.ini
> >  create mode 100644 QuarkPlatformPkg/QuarkCapsule.dsc
> >  create mode 100644 QuarkPlatformPkg/QuarkCapsule.fdf
> >  create mode 100644
> > SecurityPkg/Library/FmpAuthenticationPkcs7Lib/FmpAuthenticationPkcs7Lib
> > .c
> >  create mode 100644
> > SecurityPkg/Library/FmpAuthenticationPkcs7Lib/FmpAuthenticationPkcs7Lib
> > .inf
> >  create mode 100644
> > SecurityPkg/Library/FmpAuthenticationPkcs7Lib/FmpAuthenticationPkcs7Lib
> > .uni
> >  create mode 100644
> > SecurityPkg/Library/FmpAuthenticationRsa2048Sha256Lib/FmpAuthenticatio
> > nRsa2048Sha256Lib.c
> >  create mode 100644
> > SecurityPkg/Library/FmpAuthenticationRsa2048Sha256Lib/FmpAuthenticatio
> > nRsa2048Sha256Lib.inf
> >  create mode 100644
> > SecurityPkg/Library/FmpAuthenticationRsa2048Sha256Lib/FmpAuthenticatio
> > nRsa2048Sha256Lib.uni
> >  create mode 100644
> > UefiCpuPkg/Application/MicrocodeCapsuleApp/AppSupport.c
> >  create mode 100644
> > UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.c
> >  create mode 100644
> > UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.inf
> >  create mode 100644
> > UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.uni
> >  create mode 100644
> > UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleAppExtra.
> > uni
> >  create mode 100644
> > UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleDump.c
> >  create mode 100644 UefiCpuPkg/Include/Guid/MicrocodeFmp.h
> >  create mode 100644
> > UefiCpuPkg/Include/Library/MicrocodeFlashAccessLib.h
> >  create mode 100644
> > UefiCpuPkg/Library/MicrocodeFlashAccessLibNull/MicrocodeFlashAccessLib
> > Null.c
> >  create mode 100644
> > UefiCpuPkg/Library/MicrocodeFlashAccessLibNull/MicrocodeFlashAccessLib
> > Null.inf
> >  create mode 100644
> > UefiCpuPkg/Library/MicrocodeFlashAccessLibNull/MicrocodeFlashAccessLib
> > Null.uni
> >  create mode 100644 UefiCpuPkg/MicrocodeUpdate/MicrocodeFmp.c
> >  create mode 100644 UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.c
> >  create mode 100644 UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.h
> >  create mode 100644 UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.inf
> >  create mode 100644
> > UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdateDxe.uni
> >  create mode 100644
> > UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdateDxeExtra.uni
> >  create mode 100644
> > Vlv2TbltDevicePkg/Feature/Capsule/Library/PlatformFlashAccessLib/Platfor
> > mFlashAccessLib.c
> >  create mode 100644
> > Vlv2TbltDevicePkg/Feature/Capsule/Library/PlatformFlashAccessLib/Platfor
> > mFlashAccessLib.inf
> >  create mode 100644
> > Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescr
> > iptor.aslc
> >  create mode 100644
> > Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescr
> > iptor.inf
> >  create mode 100644
> > Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescr
> > iptorPei.c
> >  create mode 100644
> > Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosUpdateConfig/SystemBiosU
> > pdateConfig.ini
> >  create mode 100644
> > Vlv2TbltDevicePkg/Feature/Capsule/SystemBiosUpdateConfig/SystemBiosU
> > pdateConfigGcc.ini
> >  create mode 100644
> > Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLibDxe.c
> >  create mode 100644
> > Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLibDxe.inf
> >  create mode 100644
> > Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLibDxeRuntimeSmm.c
> >  create mode 100644 Vlv2TbltDevicePkg/PlatformCapsule.dsc
> >  create mode 100644 Vlv2TbltDevicePkg/PlatformCapsule.fdf
> >  create mode 100644 Vlv2TbltDevicePkg/PlatformCapsuleGcc.fdf
> >
> > --
> > 2.7.4.windows.1
> >
> > _______________________________________________
> > edk2-devel mailing list
> > edk2-devel@lists.01.org
> > https://lists.01.org/mailman/listinfo/edk2-devel


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

* Re: [PATCH 37/45] QuarkPlatformPkg/dsc/fdf: add capsule generation DSC/FDF.
  2016-09-21  6:45 ` [PATCH 37/45] QuarkPlatformPkg/dsc/fdf: add capsule generation DSC/FDF Jiewen Yao
@ 2016-09-29  1:01   ` Kinney, Michael D
  2016-09-29  2:33     ` Yao, Jiewen
  0 siblings, 1 reply; 83+ messages in thread
From: Kinney, Michael D @ 2016-09-29  1:01 UTC (permalink / raw)
  To: Yao, Jiewen, edk2-devel@lists.01.org, Kinney, Michael D
  Cc: Steele, Kelly, Tian, Feng, Zeng, Star, Gao, Liming, Zhang, Chao B

Jiewen,

This DSC/FDF generates a build failure for me from GenFds.  
I have entered a BaseTools bug into Bugzilla

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

There is a workaround to create the file that is missing
GenFds can work, so I was able to generate a Capsule
Image for FW update and saw it work.

My other major feedback on this DSC/FDF file is why this 
Content was not added to Quark DSC/FDF with #ifdef for 
RECOVERY_ENABLE and CAPSULE_ENABLE flags?

Is the [Capsule.BiosCapsuleFmpRsa2048] section really
the recovery image?  Can we use Recovery in the name
instead of Capsule?

Thanks,

Mike

> -----Original Message-----
> From: Yao, Jiewen
> Sent: Tuesday, September 20, 2016 11:45 PM
> To: edk2-devel@lists.01.org
> Cc: Kinney, Michael D <michael.d.kinney@intel.com>; Steele, Kelly
> <kelly.steele@intel.com>; Tian, Feng <feng.tian@intel.com>; Zeng, Star
> <star.zeng@intel.com>; Gao, Liming <liming.gao@intel.com>; Zhang, Chao B
> <chao.b.zhang@intel.com>
> Subject: [PATCH 37/45] QuarkPlatformPkg/dsc/fdf: add capsule generation DSC/FDF.
> 
> Add DSC/FDF to generate capsule image.
> It is separated from normal DSC/FDF, because the FDF file need use
> the result of final build.
> 
> Cc: Michael D Kinney <michael.d.kinney@intel.com>
> Cc: Kelly Steele <kelly.steele@intel.com>
> Cc: Feng Tian <feng.tian@intel.com>
> Cc: Star Zeng <star.zeng@intel.com>
> Cc: Liming Gao <liming.gao@intel.com>
> Cc: Chao Zhang <chao.b.zhang@intel.com>
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
> ---
>  QuarkPlatformPkg/QuarkCapsule.dsc | 44 +++++++++++
>  QuarkPlatformPkg/QuarkCapsule.fdf | 82 ++++++++++++++++++++
>  2 files changed, 126 insertions(+)
> 
> diff --git a/QuarkPlatformPkg/QuarkCapsule.dsc b/QuarkPlatformPkg/QuarkCapsule.dsc
> new file mode 100644
> index 0000000..3785cbd
> --- /dev/null
> +++ b/QuarkPlatformPkg/QuarkCapsule.dsc
> @@ -0,0 +1,44 @@
> +## @file
> +# Clanton Peak CRB platform with 32-bit DXE for 4MB/8MB flash devices.
> +#
> +# This package provides Clanton Peak CRB platform specific capsule.
> +# Copyright (c) 2016 Intel Corporation.
> +#
> +# This program and the accompanying materials
> +# are licensed and made available under the terms and conditions of the BSD License
> +# which accompanies this distribution.  The full text of the license may be found at
> +# http://opensource.org/licenses/bsd-license.php
> +#
> +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +#
> +##
> +
> +[Defines]
> +  PLATFORM_NAME                  = Quark
> +  PLATFORM_GUID                  = 3B9F8782-0799-450C-ACB3-2D8F4504810F
> +  PLATFORM_VERSION               = 0.1
> +  FLASH_DEFINITION               = QuarkPlatformPkg/QuarkCapsule.fdf
> +  OUTPUT_DIRECTORY               = Build/Quark
> +  SUPPORTED_ARCHITECTURES        = IA32
> +  BUILD_TARGETS                  = DEBUG|RELEASE
> +  SKUID_IDENTIFIER               = DEFAULT
> +
> +######################################################################################
> #############
> +#
> +# Components Section - list of the modules and components that will be processed by
> compilation
> +#                      tools and the EDK II tools to generate PE32/PE32+/Coff image
> files.
> +#
> +# Note: The EDK II DSC file is not used to specify how compiled binary images get
> placed
> +#       into firmware volume images. This section is just a list of modules to compile
> from
> +#       source into UEFI-compliant binaries.
> +#       It is the FDF file that contains information on combining binary files into
> firmware
> +#       volume images, whose concept is beyond UEFI and is described in PI
> specification.
> +#       Binary modules do not need to be listed in this section, as they should be
> +#       specified in the FDF file. For example: Shell binary, FAT binary (Fat.efi),
> +#       Logo (Logo.bmp), and etc.
> +#       There may also be modules listed in this section that are not required in the
> FDF file,
> +#       When a module listed here is excluded from FDF file, then UEFI-compliant
> binary will be
> +#       generated for it, but the binary will not be put into any firmware volume.
> +#
> +######################################################################################
> #############
> diff --git a/QuarkPlatformPkg/QuarkCapsule.fdf b/QuarkPlatformPkg/QuarkCapsule.fdf
> new file mode 100644
> index 0000000..d9dac51
> --- /dev/null
> +++ b/QuarkPlatformPkg/QuarkCapsule.fdf
> @@ -0,0 +1,82 @@
> +## @file
> +# FDF file of Clanton Peak CRB platform with 32-bit DXE
> +#
> +# This package provides QuarkNcSocId platform specific capsule.
> +# Copyright (c) 2016 Intel Corporation.
> +#
> +# This program and the accompanying materials
> +# are licensed and made available under the terms and conditions of the BSD License
> +# which accompanies this distribution.  The full text of the license may be found at
> +# http://opensource.org/licenses/bsd-license.php
> +#
> +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +#
> +##
> +
> +[FV.BiosUpdateCargo]
> +FvAlignment        = 16
> +ERASE_POLARITY     = 1
> +MEMORY_MAPPED      = TRUE
> +STICKY_WRITE       = TRUE
> +LOCK_CAP           = TRUE
> +LOCK_STATUS        = TRUE
> +WRITE_DISABLED_CAP = TRUE
> +WRITE_ENABLED_CAP  = TRUE
> +WRITE_STATUS       = TRUE
> +WRITE_LOCK_CAP     = TRUE
> +WRITE_LOCK_STATUS  = TRUE
> +READ_DISABLED_CAP  = TRUE
> +READ_ENABLED_CAP   = TRUE
> +READ_STATUS        = TRUE
> +READ_LOCK_CAP      = TRUE
> +READ_LOCK_STATUS   = TRUE
> +
> +FILE RAW = AF9C9EB2-12AD-4D3E-A4D4-96F6C9966215 {
> +    $(OUTPUT_DIRECTORY)/$(TARGET)_$(TOOL_CHAIN_TAG)/FV/QUARK.fd
> +  }
> +
> +FILE RAW = ce57b167-b0e4-41e8-a897-5f4feb781d40 {
> +    $(OUTPUT_DIRECTORY)/$(TARGET)_$(TOOL_CHAIN_TAG)/FV/CAPSULEDISPATCHFV.Fv
> +  }
> +
> +FILE RAW = 812136D3-4D3A-433A-9418-29BB9BF78F6E {
> +    QuarkPlatformPkg/Feature/Capsule/SystemBiosUpdateConfig/SystemBiosUpdateConfig.ini
> +  }
> +
> +[FmpPayload.FmpPayloadBiosPkcs7]
> +IMAGE_HEADER_INIT_VERSION = 0x02
> +IMAGE_TYPE_ID             = 62af20c0-7016-424a-9bf8-9ccc86584090 # System FMP special
> Guid (do not change it)
> +IMAGE_INDEX               = 0x1
> +HARDWARE_INSTANCE         = 0x0
> +MONOTONIC_COUNT           = 0x2
> +CERTIFICATE_GUID          = 4AAFD29D-68DF-49EE-8AA9-347D375665A7 # PKCS7
> +
> +FILE DATA =
> $(WORKSPACE)/$(OUTPUT_DIRECTORY)/$(TARGET)_$(TOOL_CHAIN_TAG)/FV/BIOSUPDATECARGO.Fv
> +
> +[FmpPayload.FmpPayloadBiosRsa2048]
> +IMAGE_HEADER_INIT_VERSION = 0x02
> +IMAGE_TYPE_ID             = 62af20c0-7016-424a-9bf8-9ccc86584090 # System FMP special
> Guid (do not change it)
> +IMAGE_INDEX               = 0x1
> +HARDWARE_INSTANCE         = 0x0
> +MONOTONIC_COUNT           = 0x2
> +CERTIFICATE_GUID          = A7717414-C616-4977-9420-844712A735BF # RSA2048SHA256
> +
> +FILE DATA =
> $(WORKSPACE)/$(OUTPUT_DIRECTORY)/$(TARGET)_$(TOOL_CHAIN_TAG)/FV/BIOSUPDATECARGO.Fv
> +
> +[Capsule.BiosCapsuleFmpPkcs7]
> +CAPSULE_GUID                = 6dcbd5ed-e82d-4c44-bda1-7194199ad92a # FMP special Guid
> (do not change it)
> +CAPSULE_FLAGS               = PersistAcrossReset,InitiateReset
> +CAPSULE_HEADER_SIZE         = 0x20
> +CAPSULE_HEADER_INIT_VERSION = 0x1
> +
> +FMP_PAYLOAD = FmpPayloadBiosPkcs7
> +
> +[Capsule.BiosCapsuleFmpRsa2048]
> +CAPSULE_GUID                = 6dcbd5ed-e82d-4c44-bda1-7194199ad92a # FMP special Guid
> (do not change it)
> +CAPSULE_FLAGS               = PersistAcrossReset,InitiateReset
> +CAPSULE_HEADER_SIZE         = 0x20
> +CAPSULE_HEADER_INIT_VERSION = 0x1
> +
> +FMP_PAYLOAD = FmpPayloadBiosRsa2048
> +
> --
> 2.7.4.windows.1



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

* Re: [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application.
  2016-09-21  6:44 ` [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application Jiewen Yao
@ 2016-09-29  1:06   ` Kinney, Michael D
  2016-09-29  2:37     ` Yao, Jiewen
  0 siblings, 1 reply; 83+ messages in thread
From: Kinney, Michael D @ 2016-09-29  1:06 UTC (permalink / raw)
  To: Yao, Jiewen, edk2-devel@lists.01.org, Kinney, Michael D
  Cc: Tian, Feng, Zeng, Star, Gao, Liming, Zhang, Chao B

Jiewen,

Does the capsule on disk feature provided by this app work?

I tried it with the QuarkPlatformPkg capsule and I can get
The app to copy the capsule to an EFI System Partition, but
The logic after that point looks incomplete.

Also, if I clear the Persist and Reset flags on the capsule,
the immediate processing of the capsule does not work.

Is there any FW code that will look for capsules on disk?

If there are incomplete features in CapsuleApp, then I think 
we should remove them.

Mike

> -----Original Message-----
> From: Yao, Jiewen
> Sent: Tuesday, September 20, 2016 11:45 PM
> To: edk2-devel@lists.01.org
> Cc: Tian, Feng <feng.tian@intel.com>; Zeng, Star <star.zeng@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: [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application.
> 
> This CapsuleApp can help perform capsule update in UEFI shell environment.
> It can also dump capsule information, capsule status variable, ESRT and FMP.
> 
> Cc: Feng Tian <feng.tian@intel.com>
> Cc: Star Zeng <star.zeng@intel.com>
> Cc: Michael D Kinney <michael.d.kinney@intel.com>
> Cc: Liming Gao <liming.gao@intel.com>
> Cc: Chao Zhang <chao.b.zhang@intel.com>
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
> ---
>  MdeModulePkg/Application/CapsuleApp/AppSupport.c        |  480 +++++++++
>  MdeModulePkg/Application/CapsuleApp/CapsuleApp.c        | 1047 ++++++++++++++++++++
>  MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf      |   71 ++
>  MdeModulePkg/Application/CapsuleApp/CapsuleApp.uni      |   22 +
>  MdeModulePkg/Application/CapsuleApp/CapsuleAppExtra.uni |   19 +
>  MdeModulePkg/Application/CapsuleApp/CapsuleDump.c       |  840 ++++++++++++++++
>  6 files changed, 2479 insertions(+)
> 
> diff --git a/MdeModulePkg/Application/CapsuleApp/AppSupport.c
> b/MdeModulePkg/Application/CapsuleApp/AppSupport.c
> new file mode 100644
> index 0000000..365067d
> --- /dev/null
> +++ b/MdeModulePkg/Application/CapsuleApp/AppSupport.c
> @@ -0,0 +1,480 @@
> +/** @file
> +  A shell application that triggers capsule update process.
> +
> +  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the BSD License
> +  which accompanies this distribution.  The full text of the license may be found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +
> +**/
> +
> +#include <Uefi.h>
> +#include <Library/BaseLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/UefiRuntimeServicesTableLib.h>
> +#include <Library/UefiLib.h>
> +#include <Library/PrintLib.h>
> +#include <Protocol/LoadedImage.h>
> +#include <Protocol/SimpleFileSystem.h>
> +#include <Guid/FileInfo.h>
> +#include <Guid/Gpt.h>
> +
> +#define MAX_ARG_NUM     11
> +
> +UINTN  Argc = 0;
> +CHAR16 *Argv[MAX_ARG_NUM];
> +CHAR16 *ArgBuffer;
> +
> +/**
> +
> +  This function parse application ARG.
> +
> +  @return Status
> +**/
> +EFI_STATUS
> +GetArg (
> +  VOID
> +  )
> +{
> +  UINT8                         *Data;
> +  UINTN                         DataSize;
> +  CHAR16                        *Index;
> +  CHAR16                        *End;
> +  CHAR16                        *DIndex;
> +  EFI_STATUS                    Status;
> +  EFI_LOADED_IMAGE_PROTOCOL     *LoadedImage;
> +
> +  Status = gBS->HandleProtocol (
> +                  gImageHandle,
> +                  &gEfiLoadedImageProtocolGuid,
> +                  (VOID**)&LoadedImage
> +                  );
> +  if (EFI_ERROR(Status)) {
> +    return Status;
> +  }
> +
> +  Data = LoadedImage->LoadOptions;
> +  DataSize = LoadedImage->LoadOptionsSize;
> +
> +  End = (CHAR16*)(UINTN)(Data + DataSize);
> +  Status = gBS->AllocatePool (EfiBootServicesData, DataSize, (VOID **)&ArgBuffer);
> +  ASSERT_EFI_ERROR (Status);
> +  DIndex = ArgBuffer;
> +  Argv[Argc++] = ArgBuffer;
> +  for (Index = (CHAR16*)Data; Index < End; ) {
> +    if (*Index == L' ') {
> +      *DIndex = L'\0';
> +      if (Argc >= MAX_ARG_NUM) {
> +        return EFI_UNSUPPORTED;
> +      }
> +      Argv[Argc++] = (++ DIndex);
> +      while(*Index == L' ') {
> +        Index ++;
> +      }
> +    }
> +    (*(DIndex ++)) = (*(Index ++));
> +  }
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Clear APP ARG.
> +**/
> +VOID
> +CleanArg (
> +  VOID
> +  )
> +{
> +  FreePool (Argv[0]);
> +}
> +
> +/**
> +  Return File System Volume containing this shell application.
> +
> +  @return File System Volume containing this shell application.
> +**/
> +EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *
> +GetMyVol (
> +  VOID
> +  )
> +{
> +  EFI_STATUS                        Status;
> +  EFI_LOADED_IMAGE_PROTOCOL         *LoadedImage;
> +  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Vol;
> +
> +  Status = gBS->HandleProtocol (
> +                  gImageHandle,
> +                  &gEfiLoadedImageProtocolGuid,
> +                  (VOID **)&LoadedImage
> +                  );
> +  ASSERT_EFI_ERROR (Status);
> +
> +  Status = gBS->HandleProtocol (
> +                  LoadedImage->DeviceHandle,
> +                  &gEfiSimpleFileSystemProtocolGuid,
> +                  (VOID **)&Vol
> +                  );
> +  if (!EFI_ERROR (Status)) {
> +    return Vol;
> +  }
> +
> +  return NULL;
> +}
> +
> +/**
> +  Read a file from this volume.
> +
> +  @param Vol             File System Volume
> +  @param FileName        The file to be read.
> +  @param BufferSize      The file buffer size
> +  @param Buffer          The file buffer
> +
> +  @retval EFI_SUCCESS    Read file successfully
> +  @retval EFI_NOT_FOUND  File not found
> +**/
> +EFI_STATUS
> +ReadFileFromVol (
> +  IN  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Vol,
> +  IN  CHAR16                            *FileName,
> +  OUT UINTN                             *BufferSize,
> +  OUT VOID                              **Buffer
> +  )
> +{
> +  EFI_STATUS                        Status;
> +  EFI_FILE_HANDLE                   RootDir;
> +  EFI_FILE_HANDLE                   Handle;
> +  UINTN                             FileInfoSize;
> +  EFI_FILE_INFO                     *FileInfo;
> +  UINTN                             TempBufferSize;
> +  VOID                              *TempBuffer;
> +
> +  //
> +  // Open the root directory
> +  //
> +  Status = Vol->OpenVolume (Vol, &RootDir);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  //
> +  // Open the file
> +  //
> +  Status = RootDir->Open (
> +                      RootDir,
> +                      &Handle,
> +                      FileName,
> +                      EFI_FILE_MODE_READ,
> +                      0
> +                      );
> +  if (EFI_ERROR (Status)) {
> +    RootDir->Close (RootDir);
> +    return Status;
> +  }
> +
> +  RootDir->Close (RootDir);
> +
> +  //
> +  // Get the file information
> +  //
> +  FileInfoSize = sizeof(EFI_FILE_INFO) + 1024;
> +
> +  FileInfo = AllocateZeroPool (FileInfoSize);
> +  if (FileInfo == NULL) {
> +    Handle->Close (Handle);
> +    return Status;
> +  }
> +
> +  Status = Handle->GetInfo (
> +                     Handle,
> +                     &gEfiFileInfoGuid,
> +                     &FileInfoSize,
> +                     FileInfo
> +                     );
> +  if (EFI_ERROR (Status)) {
> +    Handle->Close (Handle);
> +    gBS->FreePool (FileInfo);
> +    return Status;
> +  }
> +
> +  //
> +  // Allocate buffer for the file data. The last CHAR16 is for L'\0'
> +  //
> +  TempBufferSize = (UINTN) FileInfo->FileSize + sizeof(CHAR16);
> +  TempBuffer = AllocateZeroPool (TempBufferSize);
> +  if (TempBuffer == NULL) {
> +    Handle->Close (Handle);
> +    gBS->FreePool (FileInfo);
> +    return Status;
> +  }
> +
> +  gBS->FreePool (FileInfo);
> +
> +  //
> +  // Read the file data to the buffer
> +  //
> +  Status = Handle->Read (
> +                     Handle,
> +                     &TempBufferSize,
> +                     TempBuffer
> +                     );
> +  if (EFI_ERROR (Status)) {
> +    Handle->Close (Handle);
> +    gBS->FreePool (TempBuffer);
> +    return Status;
> +  }
> +
> +  Handle->Close (Handle);
> +
> +  *BufferSize = TempBufferSize;
> +  *Buffer     = TempBuffer;
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Read a file.
> +  If ScanFs is FLASE, it will use this Vol as default Fs.
> +  If ScanFs is TRUE, it will scan all FS and check the file.
> +    If there is only one file match the name, it will be read.
> +    If there is more than one file match the name, it will return Error.
> +
> +  @param ThisVol         File System Volume
> +  @param FileName        The file to be read.
> +  @param BufferSize      The file buffer size
> +  @param Buffer          The file buffer
> +  @param ScanFs          Need Scan all FS
> +
> +  @retval EFI_SUCCESS    Read file successfully
> +  @retval EFI_NOT_FOUND  File not found
> +  @retval EFI_NO_MAPPING There is duplicated files found
> +**/
> +EFI_STATUS
> +ReadFileToBufferEx (
> +  IN OUT EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   **ThisVol,
> +  IN  CHAR16                               *FileName,
> +  OUT UINTN                                *BufferSize,
> +  OUT VOID                                 **Buffer,
> +  IN  BOOLEAN                              ScanFs
> +  )
> +{
> +  EFI_STATUS                        Status;
> +  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Vol;
> +  UINTN                             TempBufferSize;
> +  VOID                              *TempBuffer;
> +  UINTN                             NoHandles;
> +  EFI_HANDLE                        *HandleBuffer;
> +  UINTN                             Index;
> +
> +  //
> +  // Check parameters
> +  //
> +  if ((FileName == NULL) || (Buffer == NULL) || (ThisVol == NULL)) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  //
> +  // not scan fs
> +  //
> +  if (!ScanFs) {
> +    if (*ThisVol == NULL) {
> +      *ThisVol = GetMyVol ();
> +      if (*ThisVol == NULL) {
> +        return EFI_INVALID_PARAMETER;
> +      }
> +    }
> +    //
> +    // Read file directly from Vol
> +    //
> +    return ReadFileFromVol (*ThisVol, FileName, BufferSize, Buffer);
> +  }
> +
> +  //
> +  // need scan fs
> +  //
> +
> +  //
> +  // Get all Vol handle
> +  //
> +  Status = gBS->LocateHandleBuffer (
> +                   ByProtocol,
> +                   &gEfiSimpleFileSystemProtocolGuid,
> +                   NULL,
> +                   &NoHandles,
> +                   &HandleBuffer
> +                   );
> +  if (EFI_ERROR (Status) && (NoHandles == 0)) {
> +    return EFI_NOT_FOUND;
> +  }
> +
> +  //
> +  // Walk through each Vol
> +  //
> +  *ThisVol = NULL;
> +  *BufferSize = 0;
> +  *Buffer     = NULL;
> +  for (Index = 0; Index < NoHandles; Index++) {
> +    Status = gBS->HandleProtocol (
> +                    HandleBuffer[Index],
> +                    &gEfiSimpleFileSystemProtocolGuid,
> +                    (VOID **)&Vol
> +                    );
> +    if (EFI_ERROR(Status)) {
> +      continue;
> +    }
> +
> +    Status = ReadFileFromVol (Vol, FileName, &TempBufferSize, &TempBuffer);
> +    if (!EFI_ERROR (Status)) {
> +      //
> +      // Read file OK, check duplication
> +      //
> +      if (*ThisVol != NULL) {
> +        //
> +        // Find the duplicated file
> +        //
> +        gBS->FreePool (TempBuffer);
> +        gBS->FreePool (*Buffer);
> +        Print (L"Duplicated FileName found!\n");
> +        return EFI_NO_MAPPING;
> +      } else {
> +        //
> +        // Record value
> +        //
> +        *ThisVol = Vol;
> +        *BufferSize = TempBufferSize;
> +        *Buffer     = TempBuffer;
> +      }
> +    }
> +  }
> +
> +  //
> +  // Scan Fs done
> +  //
> +  if (*ThisVol == NULL) {
> +    return EFI_NOT_FOUND;
> +  }
> +
> +  //
> +  // Done
> +  //
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Read a file.
> +
> +  @param FileName        The file to be read.
> +  @param BufferSize      The file buffer size
> +  @param Buffer          The file buffer
> +
> +  @retval EFI_SUCCESS    Read file successfully
> +  @retval EFI_NOT_FOUND  File not found
> +**/
> +EFI_STATUS
> +ReadFileToBuffer (
> +  IN  CHAR16                               *FileName,
> +  OUT UINTN                                *BufferSize,
> +  OUT VOID                                 **Buffer
> +  )
> +{
> +  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Vol;
> +  Vol = NULL;
> +  return ReadFileToBufferEx(&Vol, FileName, BufferSize, Buffer, FALSE);
> +}
> +
> +/**
> +  Write a file.
> +
> +  @param FileName        The file to be written.
> +  @param BufferSize      The file buffer size
> +  @param Buffer          The file buffer
> +
> +  @retval EFI_SUCCESS    Write file successfully
> +**/
> +EFI_STATUS
> +WriteFileFromBuffer(
> +  IN  CHAR16                               *FileName,
> +  IN  UINTN                                BufferSize,
> +  IN  VOID                                 *Buffer
> +  )
> +{
> +  EFI_STATUS                        Status;
> +  EFI_FILE_HANDLE                   RootDir;
> +  EFI_FILE_HANDLE                   Handle;
> +  UINTN                             TempBufferSize;
> +  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Vol;
> +
> +  Vol = GetMyVol();
> +
> +  //
> +  // Open the root directory
> +  //
> +  Status = Vol->OpenVolume (Vol, &RootDir);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  //
> +  // Open the file
> +  //
> +  Status = RootDir->Open (
> +                      RootDir,
> +                      &Handle,
> +                      FileName,
> +                      EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE| EFI_FILE_MODE_CREATE,
> +                      0
> +                      );
> +  if (EFI_ERROR (Status)) {
> +    RootDir->Close (RootDir);
> +    return Status;
> +  }
> +
> +  //
> +  // Delete file
> +  //
> +  Status = Handle->Delete(Handle);
> +  if (EFI_ERROR(Status)) {
> +    return Status;
> +  }
> +
> +  //
> +  // Open the file again
> +  //
> +  Status = RootDir->Open (
> +                      RootDir,
> +                      &Handle,
> +                      FileName,
> +                      EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE| EFI_FILE_MODE_CREATE,
> +                      0
> +                      );
> +  if (EFI_ERROR (Status)) {
> +    RootDir->Close (RootDir);
> +    return Status;
> +  }
> +
> +  RootDir->Close (RootDir);
> +
> +  //
> +  // Write the file data from the buffer
> +  //
> +  TempBufferSize = BufferSize;
> +  Status = Handle->Write (
> +                     Handle,
> +                     &TempBufferSize,
> +                     Buffer
> +                     );
> +  if (EFI_ERROR (Status)) {
> +    Handle->Close (Handle);
> +    return Status;
> +  }
> +
> +  Handle->Close (Handle);
> +
> +  return EFI_SUCCESS;
> +}
> +
> diff --git a/MdeModulePkg/Application/CapsuleApp/CapsuleApp.c
> b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.c
> new file mode 100644
> index 0000000..0a28557
> --- /dev/null
> +++ b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.c
> @@ -0,0 +1,1047 @@
> +/** @file
> +  A shell application that triggers capsule update process.
> +
> +  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the BSD License
> +  which accompanies this distribution.  The full text of the license may be found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +
> +**/
> +
> +#include <Uefi.h>
> +#include <Library/BaseLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/UefiRuntimeServicesTableLib.h>
> +#include <Library/UefiLib.h>
> +#include <Library/PrintLib.h>
> +#include <Protocol/LoadedImage.h>
> +#include <Protocol/SimpleFileSystem.h>
> +#include <Protocol/GraphicsOutput.h>
> +#include <Guid/FileInfo.h>
> +#include <Guid/Gpt.h>
> +#include <Guid/GlobalVariable.h>
> +#include <Guid/CapsuleReport.h>
> +#include <Guid/SystemResourceTable.h>
> +#include <Guid/FmpCapsule.h>
> +#include <IndustryStandard/WindowsUxCapsule.h>
> +
> +#define CAPSULE_HEADER_SIZE  0x20
> +
> +#define NESTED_CAPSULE_HEADER_SIZE  SIZE_4KB
> +#define SYSTEM_FIRMWARE_FLAG 0x50000
> +#define DEVICE_FIRMWARE_FLAG 0x78010
> +
> +#define EFI_CAPSULE_FROM_FILE_DIR                           L"\\EFI\\UpdateCapsule\\"
> +#define EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED  0x0000000000000004
> +
> +#define MAJOR_VERSION   1
> +#define MINOR_VERSION   0
> +
> +#define MAX_ARG_NUM     11
> +#define MAX_CAPSULE_NUM (MAX_ARG_NUM - 1)
> +
> +extern UINTN  Argc;
> +extern CHAR16 *Argv[];
> +
> +//
> +// Define how many block descriptors we want to test with.
> +//
> +UINTN  NumberOfDescriptors = 1;
> +UINTN  CapsuleFirstIndex;
> +UINTN  CapsuleLastIndex;
> +
> +/**
> +  Dump capsule information
> +
> +  @retval EFI_SUCCESS            The capsule information is dumped.
> +  @retval EFI_UNSUPPORTED        Input parameter is not valid.
> +**/
> +EFI_STATUS
> +DumpCapsule(
> +  VOID
> +  );
> +
> +/**
> +  Dump capsule status variable.
> +
> +  @retval EFI_SUCCESS            The capsule status variable is dumped.
> +  @retval EFI_UNSUPPORTED        Input parameter is not valid.
> +**/
> +EFI_STATUS
> +DmpCapsuleStatusVariable(
> +  VOID
> +  );
> +
> +/**
> +  Dump FMP protocol info.
> +**/
> +VOID
> +DumpFmpData(
> +  VOID
> +  );
> +
> +/**
> +  Dump ESRT info.
> +**/
> +VOID
> +DumpEsrtData(
> +  VOID
> +  );
> +
> +/**
> +  Read a file.
> +
> +  @param FileName        The file to be read.
> +  @param BufferSize      The file buffer size
> +  @param Buffer          The file buffer
> +
> +  @retval EFI_SUCCESS    Read file successfully
> +  @retval EFI_NOT_FOUND  File not found
> +**/
> +EFI_STATUS
> +ReadFileToBuffer(
> +  IN  CHAR16                               *FileName,
> +  OUT UINTN                                *BufferSize,
> +  OUT VOID                                 **Buffer
> +  );
> +
> +/**
> +  Write a file.
> +
> +  @param FileName        The file to be written.
> +  @param BufferSize      The file buffer size
> +  @param Buffer          The file buffer
> +
> +  @retval EFI_SUCCESS    Write file successfully
> +**/
> +EFI_STATUS
> +WriteFileFromBuffer(
> +  IN  CHAR16                               *FileName,
> +  IN  UINTN                                BufferSize,
> +  IN  VOID                                 *Buffer
> +  );
> +
> +/**
> +
> +  This function parse application ARG.
> +
> +  @return Status
> +**/
> +EFI_STATUS
> +GetArg (
> +  VOID
> +  );
> +
> +/**
> +  Clear APP ARG.
> +**/
> +VOID
> +CleanArg (
> +  VOID
> +  );
> +
> +/**
> +  Create UX capsule.
> +
> +  @retval EFI_SUCCESS            The capsule header is appended.
> +  @retval EFI_UNSUPPORTED        Input parameter is not valid.
> +  @retval EFI_OUT_OF_RESOURCES   No enough resource to create UX capsule.
> +**/
> +EFI_STATUS
> +CreateBmpFmp(
> +  VOID
> +  )
> +{
> +  CHAR16                                        *OutputCapsuleName;
> +  VOID                                          *BmpBuffer;
> +  UINTN                                         FileSize;
> +  CHAR16                                        *BmpName;
> +  UINT8                                         *FullCapsuleBuffer;
> +  UINTN                                         FullCapsuleBufferSize;
> +  EFI_DISPLAY_CAPSULE                           *DisplayCapsule;
> +  EFI_STATUS                                    Status;
> +  EFI_GRAPHICS_OUTPUT_PROTOCOL                  *Gop;
> +
> +  Status = gBS->LocateProtocol(&gEfiGraphicsOutputProtocolGuid, NULL, (VOID **)&Gop);
> +  if (EFI_ERROR(Status)) {
> +    Print(L"CapsuleApp: NO GOP is found.\n");
> +    return EFI_UNSUPPORTED;
> +  }
> +  Print(L"Current GOP: Mode - %d, ", Gop->Mode->Mode);
> +  Print(L"HorizontalResolution - %d, ", Gop->Mode->Info->HorizontalResolution);
> +  Print(L"VerticalResolution - %d\n", Gop->Mode->Info->VerticalResolution);
> +  // HorizontalResolution >= BMP_IMAGE_HEADER.PixelWidth
> +  // VerticalResolution   >= BMP_IMAGE_HEADER.PixelHeight
> +
> +  if (Argc != 5) {
> +    Print(L"CapsuleApp: Invalid Parameter.\n");
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  if (StrCmp(Argv[3], L"-O") != 0) {
> +    Print(L"CapsuleApp: NO output capsule name.\n");
> +    return EFI_UNSUPPORTED;
> +  }
> +  OutputCapsuleName = Argv[4];
> +
> +  BmpBuffer = NULL;
> +  FileSize = 0;
> +  FullCapsuleBuffer = NULL;
> +
> +  BmpName = Argv[2];
> +  Status = ReadFileToBuffer(BmpName, &FileSize, &BmpBuffer);
> +  if (EFI_ERROR(Status)) {
> +    Print(L"CapsuleApp: BMP image (%s) is not found.\n", BmpName);
> +    goto Done;
> +  }
> +
> +  FullCapsuleBufferSize = sizeof(EFI_DISPLAY_CAPSULE) + FileSize;
> +  FullCapsuleBuffer = AllocatePool(FullCapsuleBufferSize);
> +  if (FullCapsuleBuffer == NULL) {
> +    Print(L"CapsuleApp: Capsule Buffer size (0x%x) too big.\n",
> FullCapsuleBufferSize);
> +    Status = EFI_OUT_OF_RESOURCES;
> +    goto Done;
> +  }
> +
> +  DisplayCapsule = (EFI_DISPLAY_CAPSULE *)FullCapsuleBuffer;
> +  CopyGuid(&DisplayCapsule->CapsuleHeader.CapsuleGuid, &gWindowsUxCapsuleGuid);
> +  DisplayCapsule->CapsuleHeader.HeaderSize = sizeof(DisplayCapsule->CapsuleHeader);
> +  DisplayCapsule->CapsuleHeader.Flags = CAPSULE_FLAGS_PERSIST_ACROSS_RESET;
> +  DisplayCapsule->CapsuleHeader.CapsuleImageSize = (UINT32)FullCapsuleBufferSize;
> +
> +  DisplayCapsule->ImagePayload.Version = 1;
> +  DisplayCapsule->ImagePayload.Checksum = 0;
> +  DisplayCapsule->ImagePayload.ImageType = 0; // BMP
> +  DisplayCapsule->ImagePayload.Reserved = 0;
> +  DisplayCapsule->ImagePayload.Mode = Gop->Mode->Mode;
> +  DisplayCapsule->ImagePayload.OffsetX = 0;
> +  DisplayCapsule->ImagePayload.OffsetY = 0;
> +
> +  CopyMem((DisplayCapsule + 1), BmpBuffer, FileSize);
> +
> +  DisplayCapsule->ImagePayload.Checksum = CalculateCheckSum8(FullCapsuleBuffer,
> FullCapsuleBufferSize);
> +
> +  Status = WriteFileFromBuffer(OutputCapsuleName, FullCapsuleBufferSize,
> FullCapsuleBuffer);
> +  Print(L"CapsuleApp: Write %s %r\n", OutputCapsuleName, Status);
> +
> +Done:
> +  if (BmpBuffer != NULL) {
> +    FreePool(BmpBuffer);
> +  }
> +
> +  if (FullCapsuleBuffer != NULL) {
> +    FreePool(FullCapsuleBuffer);
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  Get ImageTypeId in the FMP capsule header.
> +
> +  @param CapsuleHeader  The FMP capsule image header.
> +
> +  @return ImageTypeId
> +**/
> +EFI_GUID *
> +GetCapsuleImageTypeId(
> +  IN EFI_CAPSULE_HEADER                            *CapsuleHeader
> +  )
> +{
> +  EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER       *FmpCapsuleHeader;
> +  UINT64                                       *ItemOffsetList;
> +  EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader;
> +
> +  FmpCapsuleHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *)((UINT8 *)CapsuleHeader
> + CapsuleHeader->HeaderSize);
> +  ItemOffsetList = (UINT64 *)(FmpCapsuleHeader + 1);
> +  if (FmpCapsuleHeader->PayloadItemCount == 0) {
> +    return NULL;
> +  }
> +  ImageHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *)((UINT8
> *)FmpCapsuleHeader + ItemOffsetList[FmpCapsuleHeader->EmbeddedDriverCount]);
> +  return &ImageHeader->UpdateImageTypeId;
> +}
> +
> +/**
> +  Get ESRT FwType according to ImageTypeId
> +
> +  @param  ImageTypeId   ImageTypeId of an FMP capsule.
> +
> +  @return ESRT FwType
> +**/
> +UINT32
> +GetEsrtFwType(
> +  IN  EFI_GUID                                      *ImageTypeId
> +  )
> +{
> +  EFI_STATUS                 Status;
> +  EFI_SYSTEM_RESOURCE_TABLE  *Esrt;
> +  EFI_SYSTEM_RESOURCE_ENTRY  *EsrtEntry;
> +  UINTN                      Index;
> +
> +  //
> +  // Check ESRT
> +  //
> +  Status = EfiGetSystemConfigurationTable(&gEfiSystemResourceTableGuid, (VOID
> **)&Esrt);
> +  if (!EFI_ERROR(Status)) {
> +    EsrtEntry = (VOID *)(Esrt + 1);
> +    for (Index = 0; Index < Esrt->FwResourceCount; Index++, EsrtEntry++) {
> +      if (CompareGuid(&EsrtEntry->FwClass, ImageTypeId)) {
> +        return EsrtEntry->FwType;
> +      }
> +    }
> +  }
> +
> +  return ESRT_FW_TYPE_UNKNOWN;
> +}
> +
> +/**
> +  Append a capsule header on top of current image.
> +  This function follows Windows UEFI Firmware Update Platform document.
> +
> +  @retval EFI_SUCCESS            The capsule header is appended.
> +  @retval EFI_UNSUPPORTED        Input parameter is not valid.
> +  @retval EFI_OUT_OF_RESOURCES   No enough resource to append capsule header.
> +**/
> +EFI_STATUS
> +CreateNestedFmp(
> +  VOID
> +  )
> +{
> +  CHAR16                                        *OutputCapsuleName;
> +  VOID                                          *CapsuleBuffer;
> +  UINTN                                         FileSize;
> +  CHAR16                                        *CapsuleName;
> +  UINT8                                         *FullCapsuleBuffer;
> +  UINTN                                         FullCapsuleBufferSize;
> +  EFI_CAPSULE_HEADER                            *NestedCapsuleHeader;
> +  EFI_GUID                                      *ImageTypeId;
> +  UINT32                                        FwType;
> +  EFI_STATUS                                    Status;
> +
> +  if (Argc != 5) {
> +    Print(L"CapsuleApp: Invalid Parameter.\n");
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  if (StrCmp(Argv[3], L"-O") != 0) {
> +    Print(L"CapsuleApp: NO output capsule name.\n");
> +    return EFI_UNSUPPORTED;
> +  }
> +  OutputCapsuleName = Argv[4];
> +
> +  CapsuleBuffer = NULL;
> +  FileSize = 0;
> +  FullCapsuleBuffer = NULL;
> +
> +  CapsuleName = Argv[2];
> +  Status = ReadFileToBuffer(CapsuleName, &FileSize, &CapsuleBuffer);
> +  if (EFI_ERROR(Status)) {
> +    Print(L"CapsuleApp: Capsule image (%s) is not found.\n", CapsuleName);
> +    goto Done;
> +  }
> +
> +  ImageTypeId = GetCapsuleImageTypeId(CapsuleBuffer);
> +  if (ImageTypeId == NULL) {
> +    Print(L"CapsuleApp: Capsule ImageTypeId is not found.\n");
> +    goto Done;
> +  }
> +  FwType = GetEsrtFwType(ImageTypeId);
> +  if ((FwType != ESRT_FW_TYPE_SYSTEMFIRMWARE) && (FwType !=
> ESRT_FW_TYPE_DEVICEFIRMWARE)) {
> +    Print(L"CapsuleApp: Capsule FwType is invalid.\n");
> +    goto Done;
> +  }
> +
> +  FullCapsuleBufferSize = NESTED_CAPSULE_HEADER_SIZE + FileSize;
> +  FullCapsuleBuffer = AllocatePool(FullCapsuleBufferSize);
> +  if (FullCapsuleBuffer == NULL) {
> +    Print(L"CapsuleApp: Capsule Buffer size (0x%x) too big.\n",
> FullCapsuleBufferSize);
> +    Status = EFI_OUT_OF_RESOURCES;
> +    goto Done;
> +  }
> +
> +  NestedCapsuleHeader = (EFI_CAPSULE_HEADER *)FullCapsuleBuffer;
> +  ZeroMem(NestedCapsuleHeader, NESTED_CAPSULE_HEADER_SIZE);
> +  CopyGuid(&NestedCapsuleHeader->CapsuleGuid, ImageTypeId);
> +  NestedCapsuleHeader->HeaderSize = NESTED_CAPSULE_HEADER_SIZE;
> +  NestedCapsuleHeader->Flags = (FwType == ESRT_FW_TYPE_DEVICEFIRMWARE) ?
> SYSTEM_FIRMWARE_FLAG : DEVICE_FIRMWARE_FLAG;
> +  NestedCapsuleHeader->CapsuleImageSize = (UINT32)FullCapsuleBufferSize;
> +
> +  CopyMem((UINT8 *)NestedCapsuleHeader + NestedCapsuleHeader->HeaderSize,
> CapsuleBuffer, FileSize);
> +
> +  Status = WriteFileFromBuffer(OutputCapsuleName, FullCapsuleBufferSize,
> FullCapsuleBuffer);
> +  Print(L"CapsuleApp: Write %s %r\n", OutputCapsuleName, Status);
> +
> +Done:
> +  if (CapsuleBuffer != NULL) {
> +    FreePool(CapsuleBuffer);
> +  }
> +
> +  if (FullCapsuleBuffer != NULL) {
> +    FreePool(FullCapsuleBuffer);
> +  }
> +
> +  return Status;
> +}
> +
> +
> +/**
> +  Clear capsule status variable.
> +
> +  @retval EFI_SUCCESS            The capsule status variable is cleared.
> +**/
> +EFI_STATUS
> +ClearCapsuleStatusVariable(
> +  VOID
> +  )
> +{
> +  EFI_STATUS                          Status;
> +  UINT32                              Index;
> +  CHAR16                              CapsuleVarName[20];
> +  CHAR16                              *TempVarName;
> +
> +  StrCpyS (CapsuleVarName, sizeof(CapsuleVarName)/sizeof(CapsuleVarName[0]),
> L"Capsule");
> +  TempVarName = CapsuleVarName + StrLen (CapsuleVarName);
> +  Index = 0;
> +
> +  while (TRUE) {
> +    UnicodeSPrint (TempVarName, 5 * sizeof(CHAR16), L"%04x", Index);
> +
> +    Status = gRT->SetVariable (
> +                    CapsuleVarName,
> +                    &gEfiCapsuleReportGuid,
> +                    EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS |
> EFI_VARIABLE_BOOTSERVICE_ACCESS,
> +                    0,
> +                    (VOID *)NULL
> +                    );
> +    if (EFI_ERROR(Status)) {
> +      //
> +      // There is no capsule variables, quit
> +      //
> +      break;
> +    }
> +
> +    Index++;
> +    if (Index > 0xFFFF) {
> +      break;
> +    }
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Get the active UEFI system partition from bootoption list.
> +
> +  @param[out] Fs    Simple File System protocol on the active UEFI system partition
> +
> +  @retval EFI_SUCCESS   active UEFI system partition found
> +**/
> +EFI_STATUS
> +GetEfiSysPartition(
> +  OUT EFI_SIMPLE_FILE_SYSTEM_PROTOCOL **Fs
> +  )
> +{
> +  EFI_STATUS                       Status;
> +  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL  *FsTemp;
> +  UINTN                            NoHandles;
> +  EFI_HANDLE                       *Handles;
> +  UINTN                            Index;
> +
> +  Handles = NULL;
> +
> +  //
> +  // search for EFI system partition protocol on Boot option device path
> +  //
> +  Status = gBS->LocateHandleBuffer(ByProtocol, &gEfiPartTypeSystemPartGuid, NULL,
> &NoHandles, &Handles);
> +  if (EFI_ERROR(Status)) {
> +    return Status;
> +  }
> +
> +  //
> +  // Skip BootOptions within FV
> +  //
> +  for (Index = 0; Index < NoHandles; Index++) {
> +    Status = gBS->HandleProtocol (Handles[Index], &gEfiSimpleFileSystemProtocolGuid,
> (VOID **)&FsTemp);
> +    if (!EFI_ERROR (Status)){
> +      *Fs = FsTemp;
> +      break;
> +    }
> +  }
> +  return Status;
> +}
> +
> +/**
> +  Copy a list of capsule images to the active UEFI system partition from bootoption
> list.
> +
> +  @param[in] CapsuleBuffer    An array of pointer to capsule images
> +  @param[in] FileSize         An array of UINTN to capsule images size
> +  @param[in] CapsuleNum       The count of capsule images
> +
> +  @retval EFI_SUCCESS   Capsule images are copied to the active UEFI system partition
> +**/
> +EFI_STATUS
> +CopyCapsuleToActiveEfiPartition(
> +  IN VOID                          **CapsuleBuffer,
> +  IN UINTN                         *FileSize,
> +  IN UINTN                         CapsuleNum
> +  )
> +{
> +  EFI_STATUS                       Status;
> +  CHAR16                           *CapsuleName;
> +  UINTN                            Index;
> +  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL  *Fs;
> +  EFI_FILE_HANDLE                  RootDir;
> +  EFI_FILE_HANDLE                  CapsuleDir;
> +  EFI_FILE_HANDLE                  DestHandle;
> +  UINTN                            DataSize;
> +  UINT64                           OsIndication;
> +
> +  RootDir      = NULL;
> +  CapsuleDir   = NULL;
> +
> +  Status = GetEfiSysPartition(&Fs);
> +  if (EFI_ERROR(Status)) {
> +    Print (L"Can not find active UEFI System Partition\n");
> +    return Status;
> +  }
> +
> +  Status = Fs->OpenVolume(Fs, &RootDir);
> +  if (EFI_ERROR(Status)) {
> +    goto EXIT;
> +  }
> +
> +  Status = RootDir->Open(
> +                      RootDir,
> +                      &CapsuleDir,
> +                      EFI_CAPSULE_FROM_FILE_DIR,
> +                      EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE,
> +                      EFI_FILE_DIRECTORY
> +                      );
> +  if (EFI_ERROR(Status)) {
> +    goto EXIT;
> +  }
> +
> +  //
> +  // Read the input files.
> +  //
> +  for (Index = 0; Index < CapsuleNum; Index++) {
> +    CapsuleName = Argv[CapsuleFirstIndex + Index];
> +    Status = CapsuleDir->Open(
> +                           CapsuleDir,
> +                           &DestHandle,
> +                           CapsuleName,
> +                           EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE |
> EFI_FILE_MODE_CREATE,
> +                           EFI_FILE_ARCHIVE
> +                           );
> +    if (EFI_ERROR(Status)) {
> +      Print(L"CapsuleApp: %s open error - %r\n", CapsuleName, Status);
> +      continue;
> +    }
> +
> +    DataSize = FileSize[Index];
> +    Status = DestHandle->Write(
> +                           DestHandle,
> +                           &DataSize,
> +                           CapsuleBuffer[Index]
> +                           );
> +    DestHandle->Close(DestHandle);
> +    if (EFI_ERROR(Status)) {
> +      Print(L"CapsuleApp: %s write error - %r, FileSize - 0x%x\n", CapsuleName,
> Status, FileSize[Index]);
> +    }
> +  }
> +
> +  Status = gRT->GetVariable (
> +                  L"OsIndications",
> +                  &gEfiGlobalVariableGuid,
> +                  NULL,
> +                  &DataSize,
> +                  (VOID *) &OsIndication
> +                  );
> +
> +  if (EFI_ERROR(Status) || DataSize != sizeof(OsIndication)) {
> +    OsIndication = 0;
> +  }
> +
> +  //
> +  // Set OsIndications Variable EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED bit
> +  //
> +  OsIndication |= EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED;
> +  Status = gRT->SetVariable (
> +                  L"OsIndications",
> +                  &gEfiGlobalVariableGuid,
> +                  EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS |
> +                  EFI_VARIABLE_BOOTSERVICE_ACCESS,
> +                  sizeof(OsIndication),
> +                  (VOID *)&OsIndication
> +                  );
> +
> +
> +EXIT:
> +  if (RootDir != NULL) {
> +    RootDir->Close(RootDir);
> +  }
> +
> +  if (CapsuleDir != NULL) {
> +    CapsuleDir->Close(CapsuleDir);
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  Build Gather list for a list of capsule images.
> +
> +  @param[in]  CapsuleBuffer    An array of pointer to capsule images
> +  @param[in]  FileSize         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                         *FileSize,
> +  IN UINTN                         CapsuleNum,
> +  OUT EFI_CAPSULE_BLOCK_DESCRIPTOR **BlockDescriptors
> +  )
> +{
> +  EFI_STATUS                    Status;
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR  *BlockDescriptors1;
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR  *BlockDescriptors2;
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR  *BlockDescriptorPre;
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR  *BlockDescriptorsHeader;
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR  *TempBlockPtr;
> +  UINT8                         *TempDataPtr;
> +  UINTN                         SizeLeft;
> +  UINTN                         Size;
> +  INT32                         Count;
> +  INT32                         Number;
> +  UINTN                         Index;
> +
> +  TempBlockPtr           = NULL;
> +  BlockDescriptors1      = NULL;
> +  BlockDescriptors2      = NULL;
> +  BlockDescriptorPre     = NULL;
> +  BlockDescriptorsHeader = NULL;
> +
> +  for (Index = 0; Index < CapsuleNum; Index++) {
> +    //
> +    // Allocate memory for the descriptors.
> +    //
> +    if (NumberOfDescriptors == 1) {
> +      Count = 2;
> +    } else {
> +      Count = (INT32)(NumberOfDescriptors + 2) / 2;
> +    }
> +
> +    Size               = Count * sizeof (EFI_CAPSULE_BLOCK_DESCRIPTOR);
> +    BlockDescriptors1  = AllocateRuntimeZeroPool (Size);
> +    if (BlockDescriptors1 == NULL) {
> +      Print (L"CapsuleApp: failed to allocate memory for descriptors\n");
> +      Status = EFI_OUT_OF_RESOURCES;
> +      goto ERREXIT;
> +    } else {
> +      Print (L"CapsuleApp: creating capsule descriptors at 0x%X\n", (UINTN)
> BlockDescriptors1);
> +      Print (L"CapsuleApp: capsule data starts          at 0x%X with size 0x%X\n",
> (UINTN) CapsuleBuffer, FileSize);
> +    }
> +
> +    //
> +    // Record descirptor header
> +    //
> +    if (Index == 0) {
> +      BlockDescriptorsHeader = BlockDescriptors1;
> +    }
> +
> +    if (BlockDescriptorPre != NULL) {
> +      BlockDescriptorPre->Union.ContinuationPointer = (UINTN) BlockDescriptors1;
> +      BlockDescriptorPre->Length = 0;
> +    }
> +
> +    //
> +    // Fill them in
> +    //
> +    TempBlockPtr  = BlockDescriptors1;
> +    TempDataPtr   = CapsuleBuffer[Index];
> +    SizeLeft      = FileSize[Index];
> +    for (Number = 0; (Number < Count - 1) && (SizeLeft != 0); Number++) {
> +      //
> +      // Divide remaining data in half
> +      //
> +      if (NumberOfDescriptors != 1) {
> +        if (SizeLeft == 1) {
> +          Size = 1;
> +        } else {
> +          Size = SizeLeft / 2;
> +        }
> +      } else {
> +        Size = SizeLeft;
> +      }
> +      TempBlockPtr->Union.DataBlock    = (UINTN)TempDataPtr;
> +      TempBlockPtr->Length  = Size;
> +      Print (L"CapsuleApp: capsule block/size              0x%X/0x%X\n", (UINTN)
> TempDataPtr, Size);
> +      SizeLeft -= Size;
> +      TempDataPtr += Size;
> +      TempBlockPtr++;
> +    }
> +
> +    //
> +    // Allocate the second list, point the first block's last entry to point
> +    // to this one, and fill this one in. Worst case is that the previous
> +    // list only had one element that pointed here, so we need at least two
> +    // elements -- one to point to all the data, another to terminate the list.
> +    //
> +    if ((NumberOfDescriptors != 1) && (SizeLeft != 0)) {
> +      Count = (INT32)(NumberOfDescriptors + 2) - Count;
> +      if (Count == 1) {
> +        Count++;
> +      }
> +
> +      Size              = Count * sizeof (EFI_CAPSULE_BLOCK_DESCRIPTOR);
> +      BlockDescriptors2 = AllocateRuntimeZeroPool (Size);
> +      if (BlockDescriptors2 == NULL) {
> +        Print (L"CapsuleApp: failed to allocate memory for descriptors\n");
> +        Status = EFI_OUT_OF_RESOURCES;
> +        goto ERREXIT;
> +      }
> +
> +      //
> +      // Point the first list's last element to point to this second list.
> +      //
> +      TempBlockPtr->Union.ContinuationPointer   = (UINTN) BlockDescriptors2;
> +
> +      TempBlockPtr->Length  = 0;
> +      TempBlockPtr = BlockDescriptors2;
> +      for (Number = 0; Number < Count - 1; Number++) {
> +        //
> +        // If second-to-last one, then dump rest to this element
> +        //
> +        if (Number == (Count - 2)) {
> +          Size = SizeLeft;
> +        } else {
> +          //
> +          // Divide remaining data in half
> +          //
> +          if (SizeLeft == 1) {
> +            Size = 1;
> +          } else {
> +            Size = SizeLeft / 2;
> +          }
> +        }
> +
> +        TempBlockPtr->Union.DataBlock    = (UINTN)TempDataPtr;
> +        TempBlockPtr->Length  = Size;
> +        Print (L"CapsuleApp: capsule block/size              0x%X/0x%X\n", (UINTN)
> TempDataPtr, Size);
> +        SizeLeft -= Size;
> +        TempDataPtr += Size;
> +        TempBlockPtr++;
> +        if (SizeLeft == 0) {
> +          break;
> +        }
> +      }
> +    }
> +
> +    BlockDescriptorPre = TempBlockPtr;
> +    BlockDescriptors1  = NULL;
> +  }
> +
> +  //
> +  // Null-terminate.
> +  //
> +  if (TempBlockPtr != NULL) {
> +    TempBlockPtr->Union.ContinuationPointer    = (UINTN)NULL;
> +    TempBlockPtr->Length  = 0;
> +    *BlockDescriptors = BlockDescriptorsHeader;
> +  }
> +
> +  return EFI_SUCCESS;
> +
> +ERREXIT:
> +  if (BlockDescriptors1 != NULL) {
> +    FreePool(BlockDescriptors1);
> +  }
> +
> +  if (BlockDescriptors2 != NULL) {
> +    FreePool(BlockDescriptors2);
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  Clear the Gather list for a list of capsule images.
> +
> +  @param[in]  BlockDescriptors The block descriptors for the capsule images
> +  @param[in]  CapsuleNum       The count of capsule images
> +**/
> +VOID
> +CleanGatherList(
> +  IN EFI_CAPSULE_BLOCK_DESCRIPTOR   *BlockDescriptors,
> +  IN UINTN                          CapsuleNum
> +  )
> +{
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR   *TempBlockPtr;
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR   *TempBlockPtr1;
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR   *TempBlockPtr2;
> +  UINTN                          Index;
> +
> +  if (BlockDescriptors != NULL) {
> +    TempBlockPtr1 = BlockDescriptors;
> +    while (1){
> +      TempBlockPtr = TempBlockPtr1;
> +      for (Index = 0; Index < CapsuleNum; Index++) {
> +        if (TempBlockPtr[Index].Length == 0) {
> +          break;
> +        }
> +      }
> +
> +      if (TempBlockPtr[Index].Union.ContinuationPointer == (UINTN)NULL) {
> +        break;
> +      }
> +
> +      TempBlockPtr2 = (VOID *) ((UINTN) TempBlockPtr->Union.ContinuationPointer);
> +      FreePool(TempBlockPtr1);
> +      TempBlockPtr1 = TempBlockPtr2;
> +    }
> +  }
> +}
> +
> +/**
> +  Print APP usage.
> +**/
> +VOID
> +PrintUsage (
> +  VOID
> +  )
> +{
> +  Print(L"CapsuleApp:  usage\n");
> +  Print(L"  CapsuleApp [-F] <Capsule...> [-NR]\n");
> +  Print(L"  CapsuleApp -S\n");
> +  Print(L"  CapsuleApp -C\n");
> +  Print(L"  CapsuleApp -P\n");
> +  Print(L"  CapsuleApp -E\n");
> +  Print(L"  CapsuleApp -G <BMP> -O <Capsule>\n");
> +  Print(L"  CapsuleApp -N <Capsule> -O <NestedCapsule>\n");
> +  Print(L"  CapsuleApp -D|-DS <Capsule>\n");
> +  Print(L"Parameter:\n");
> +  Print(L"  -F:  Put capsule file to disk.\n");
> +  Print(L"       No -F means to put capsule file in memory.\n");
> +  Print(L"  -NR: No Reset.\n");
> +  Print(L"  -S:  Dump capsule status.\n");
> +  Print(L"  -C:  Clear capsule status.\n");
> +  Print(L"  -P:  Dump FMP protocol info.\n");
> +  Print(L"  -E:  Dump ESRT table info.\n");
> +  Print(L"  -G:  Input BMP file name\n");
> +  Print(L"  -N:  Append Capsule Header accroding to Windows Firmware Update\n");
> +  Print(L"  -O:  Output Capsule file name\n");
> +  Print(L"  -D:  Dump Capsule\n");
> +  Print(L"  -DS: Dump Capsule with System FMP format\n");
> +}
> +
> +/**
> +  Update Capsule image.
> +
> +  @param[in]  ImageHandle     The image handle.
> +  @param[in]  SystemTable     The system table.
> +
> +  @retval EFI_SUCCESS            Command completed successfully.
> +  @retval EFI_INVALID_PARAMETER  Command usage error.
> +  @retval EFI_NOT_FOUND          The input file can't be found.
> +**/
> +EFI_STATUS
> +EFIAPI
> +UefiMain (
> +  IN EFI_HANDLE        ImageHandle,
> +  IN EFI_SYSTEM_TABLE  *SystemTable
> +  )
> +{
> +  EFI_STATUS                    Status;
> +  UINTN                         FileSize[MAX_CAPSULE_NUM];
> +  VOID                          *CapsuleBuffer[MAX_CAPSULE_NUM];
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR  *BlockDescriptors;
> +  EFI_CAPSULE_HEADER             *CapsuleHeaderArray[MAX_CAPSULE_NUM + 1];
> +  UINT64                         MaxCapsuleSize;
> +  EFI_RESET_TYPE                 ResetType;
> +  BOOLEAN                        NeedReset;
> +  BOOLEAN                        NoReset;
> +  BOOLEAN                        NeedCopyOnDisk;
> +  CHAR16                         *CapsuleName;
> +  UINTN                          CapsuleNum;
> +  UINTN                          Index;
> +
> +  Status = GetArg();
> +  if (EFI_ERROR(Status)) {
> +    PrintUsage();
> +    return Status;
> +  }
> +  if (Argc < 2) {
> +    PrintUsage();
> +    CleanArg();
> +    return EFI_INVALID_PARAMETER;
> +  }
> +  if ((StrCmp(Argv[1], L"-D") == 0) ||
> +      (StrCmp(Argv[1], L"-DS") == 0)) {
> +    Status = DumpCapsule();
> +    CleanArg();
> +    return Status;
> +  }
> +  if (StrCmp(Argv[1], L"-G") == 0) {
> +    Status = CreateBmpFmp();
> +    CleanArg();
> +    return Status;
> +  }
> +  if (StrCmp(Argv[1], L"-N") == 0) {
> +    Status = CreateNestedFmp();
> +    CleanArg();
> +    return Status;
> +  }
> +  if (StrCmp(Argv[1], L"-S") == 0) {
> +    Status = DmpCapsuleStatusVariable();
> +    CleanArg();
> +    return EFI_SUCCESS;
> +  }
> +  if (StrCmp(Argv[1], L"-C") == 0) {
> +    Status = ClearCapsuleStatusVariable();
> +    CleanArg();
> +    return Status;
> +  }
> +  if (StrCmp(Argv[1], L"-P") == 0) {
> +    DumpFmpData();
> +    CleanArg();
> +    return EFI_SUCCESS;
> +  }
> +  if (StrCmp(Argv[1], L"-E") == 0) {
> +    DumpEsrtData();
> +    CleanArg();
> +    return EFI_SUCCESS;
> +  }
> +  if (StrCmp(Argv[1], L"-F") == 0) {
> +    NeedCopyOnDisk = TRUE;
> +    CapsuleFirstIndex = 2;
> +  } else {
> +    NeedCopyOnDisk = FALSE;
> +    CapsuleFirstIndex = 1;
> +  }
> +  if (StrCmp(Argv[Argc - 1], L"-NR") == 0) {
> +    NoReset = TRUE;
> +    CapsuleLastIndex = Argc - 2;
> +  } else {
> +    NoReset = FALSE;
> +    CapsuleLastIndex = Argc - 1;
> +  }
> +  CapsuleNum = CapsuleLastIndex - CapsuleFirstIndex + 1;
> +
> +  if (CapsuleFirstIndex > CapsuleLastIndex) {
> +    Print(L"CapsuleApp: NO capsule image.\n");
> +    CleanArg();
> +    return EFI_UNSUPPORTED;
> +  }
> +  if (CapsuleNum > MAX_CAPSULE_NUM) {
> +    Print(L"CapsuleApp: Too many capsule images.\n");
> +    CleanArg();
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  ZeroMem(&CapsuleBuffer, sizeof(CapsuleBuffer));
> +  ZeroMem(&FileSize, sizeof(FileSize));
> +  BlockDescriptors = NULL;
> +
> +  for (Index = 0; Index < CapsuleNum; Index++) {
> +    CapsuleName = Argv[CapsuleFirstIndex + Index];
> +    Status = ReadFileToBuffer(CapsuleName, &FileSize[Index], &CapsuleBuffer[Index]);
> +    if (EFI_ERROR(Status)) {
> +      Print(L"CapsuleApp: capsule image (%s) is not found.\n", CapsuleName);
> +      goto Done;
> +    }
> +  }
> +
> +  if (NeedCopyOnDisk) {
> +    Status = CopyCapsuleToActiveEfiPartition(CapsuleBuffer, FileSize, CapsuleNum);
> +  } else {
> +    //
> +    // Every capsule use 2 descriptor 1 for data 1 for end
> +    //
> +    Status = BuildGatherList(CapsuleBuffer, FileSize, CapsuleNum, &BlockDescriptors);
> +  }
> +  if (EFI_ERROR(Status)) {
> +    goto Done;
> +  }
> +
> +  //
> +  // Call the runtime service capsule.
> +  //
> +  NeedReset = FALSE;
> +  for (Index = 0; Index < CapsuleNum; Index++) {
> +    CapsuleHeaderArray[Index] = (EFI_CAPSULE_HEADER *) CapsuleBuffer[Index];
> +    if ((CapsuleHeaderArray[Index]->Flags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET) != 0)
> {
> +      NeedReset = TRUE;
> +    }
> +  }
> +  CapsuleHeaderArray[CapsuleNum] = NULL;
> +  if (NoReset) {
> +    NeedReset = FALSE;
> +  }
> +
> +  //
> +  // Inquire platform capability of UpdateCapsule.
> +  //
> +  Status = gRT->QueryCapsuleCapabilities (CapsuleHeaderArray, CapsuleNum,
> &MaxCapsuleSize, &ResetType);
> +  if (EFI_ERROR(Status)) {
> +    Print (L"CapsuleApp: failed to query capsule capability - %r\n", Status);
> +    goto Done;
> +  }
> +
> +  for (Index = 0; Index < CapsuleNum; Index++) {
> +    if (FileSize[Index] > MaxCapsuleSize) {
> +      Print (L"CapsuleApp: capsule is too large to update, %ld is allowed\n",
> MaxCapsuleSize);
> +      Status = EFI_UNSUPPORTED;
> +      goto Done;
> +    }
> +  }
> +
> +  //
> +  // Check whether the input capsule image has the flag of persist across system
> reset.
> +  //
> +  if (NeedReset) {
> +    Status = gRT->UpdateCapsule(CapsuleHeaderArray,CapsuleNum,(UINTN)
> BlockDescriptors);
> +    if (Status != EFI_SUCCESS) {
> +      Print (L"CapsuleApp: failed to update capsule - %r\n", Status);
> +      goto Done;
> +    }
> +    //
> +    // For capsule who has reset flag, after calling UpdateCapsule service,triger a
> +    // system reset to process capsule persist across a system reset.
> +    //
> +    gRT->ResetSystem (ResetType, EFI_SUCCESS, 0, NULL);
> +  } else {
> +    //
> +    // For capsule who has no reset flag, only call UpdateCapsule Service without a
> +    // system reset. The service will process the capsule immediately.
> +    //
> +    Status = gRT->UpdateCapsule (CapsuleHeaderArray,CapsuleNum,(UINTN)
> BlockDescriptors);
> +    if (Status != EFI_SUCCESS) {
> +      Print (L"CapsuleApp: failed to update capsule - %r\n", Status);
> +    }
> +  }
> +
> +  Status = EFI_SUCCESS;
> +
> +Done:
> +  for (Index = 0; Index < CapsuleNum; Index++) {
> +    if (CapsuleBuffer[Index] != NULL) {
> +      FreePool (CapsuleBuffer[Index]);
> +    }
> +  }
> +
> +  CleanGatherList(BlockDescriptors, CapsuleNum);
> +  CleanArg();
> +
> +  return Status;
> +}
> diff --git a/MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf
> b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf
> new file mode 100644
> index 0000000..7ee44fc
> --- /dev/null
> +++ b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf
> @@ -0,0 +1,71 @@
> +##  @file
> +#  A shell application that triggers capsule update process.
> +#
> +# This application can trigger capsule update process. It can also
> +# generate capsule image, or dump capsule variable information.
> +#
> +#  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
> +#  This program and the accompanying materials
> +#  are licensed and made available under the terms and conditions of the BSD License
> +#  which accompanies this distribution.  The full text of the license may be found at
> +#  http://opensource.org/licenses/bsd-license.php
> +#
> +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +#
> +##
> +
> +[Defines]
> +  INF_VERSION                    = 0x00010006
> +  BASE_NAME                      = CapsuleApp
> +  MODULE_UNI_FILE                = CapsuleApp.uni
> +  FILE_GUID                      = 4CEF31DA-8682-4274-9CC4-AEE7516A5E7B
> +  MODULE_TYPE                    = UEFI_APPLICATION
> +  VERSION_STRING                 = 1.0
> +  ENTRY_POINT                    = UefiMain
> +
> +#
> +# The following information is for reference only and not required by the build tools.
> +#
> +#  VALID_ARCHITECTURES           = IA32 X64
> +#
> +
> +[Sources]
> +  CapsuleApp.c
> +  CapsuleDump.c
> +  AppSupport.c
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +
> +[Guids]
> +  gEfiFileInfoGuid
> +  gEfiPartTypeSystemPartGuid
> +  gEfiGlobalVariableGuid
> +  gEfiCapsuleReportGuid
> +  gEfiFmpCapsuleGuid
> +  gWindowsUxCapsuleGuid
> +  gEfiCertTypeRsa2048Sha256Guid
> +  gEfiCertPkcs7Guid
> +  gEfiSystemResourceTableGuid
> +
> +[Protocols]
> +  gEfiLoadedImageProtocolGuid
> +  gEfiSimpleFileSystemProtocolGuid
> +  gEfiGraphicsOutputProtocolGuid
> +  gEfiFirmwareManagementProtocolGuid
> +
> +[LibraryClasses]
> +  BaseLib
> +  UefiApplicationEntryPoint
> +  DebugLib
> +  MemoryAllocationLib
> +  UefiBootServicesTableLib
> +  UefiRuntimeServicesTableLib
> +  UefiLib
> +  PrintLib
> +  EdkiiSystemCapsuleLib
> +
> +[UserExtensions.TianoCore."ExtraFiles"]
> +  CapsuleAppExtra.uni
> diff --git a/MdeModulePkg/Application/CapsuleApp/CapsuleApp.uni
> b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.uni
> new file mode 100644
> index 0000000..54d6e12
> --- /dev/null
> +++ b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.uni
> @@ -0,0 +1,22 @@
> +// /** @file
> +// A shell application that triggers capsule update process.
> +//
> +// This application can trigger capsule update process. It can also
> +// generate capsule image, or dump capsule variable information.
> +//
> +// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
> +//
> +// This program and the accompanying materials
> +// are licensed and made available under the terms and conditions of the BSD License
> +// which accompanies this distribution. The full text of the license may be found at
> +// http://opensource.org/licenses/bsd-license.php
> +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +//
> +// **/
> +
> +
> +#string STR_MODULE_ABSTRACT             #language en-US "A shell application that
> triggers capsule update process."
> +
> +#string STR_MODULE_DESCRIPTION          #language en-US "This application can trigger
> capsule update process. It can also generate capsule image, or dump capsule variable
> information."
> +
> diff --git a/MdeModulePkg/Application/CapsuleApp/CapsuleAppExtra.uni
> b/MdeModulePkg/Application/CapsuleApp/CapsuleAppExtra.uni
> new file mode 100644
> index 0000000..b5a8840
> --- /dev/null
> +++ b/MdeModulePkg/Application/CapsuleApp/CapsuleAppExtra.uni
> @@ -0,0 +1,19 @@
> +// /** @file
> +// CapsuleApp Localized Strings and Content
> +//
> +// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
> +//
> +// This program and the accompanying materials
> +// are licensed and made available under the terms and conditions of the BSD License
> +// which accompanies this distribution. The full text of the license may be found at
> +// http://opensource.org/licenses/bsd-license.php
> +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +//
> +// **/
> +
> +#string STR_PROPERTIES_MODULE_NAME
> +#language en-US
> +"Capsule Application"
> +
> +
> diff --git a/MdeModulePkg/Application/CapsuleApp/CapsuleDump.c
> b/MdeModulePkg/Application/CapsuleApp/CapsuleDump.c
> new file mode 100644
> index 0000000..c56f41f
> --- /dev/null
> +++ b/MdeModulePkg/Application/CapsuleApp/CapsuleDump.c
> @@ -0,0 +1,840 @@
> +/** @file
> +  Dump Capsule image information.
> +
> +  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the BSD License
> +  which accompanies this distribution.  The full text of the license may be found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +
> +**/
> +
> +#include <PiDxe.h>
> +#include <Library/BaseLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/UefiRuntimeServicesTableLib.h>
> +#include <Library/UefiLib.h>
> +#include <Library/PrintLib.h>
> +#include <Library/EdkiiSystemCapsuleLib.h>
> +#include <Protocol/FirmwareManagement.h>
> +#include <Guid/ImageAuthentication.h>
> +#include <Guid/EdkiiSystemFmpCapsule.h>
> +#include <Guid/CapsuleReport.h>
> +#include <Guid/SystemResourceTable.h>
> +#include <Guid/FmpCapsule.h>
> +#include <IndustryStandard/WindowsUxCapsule.h>
> +
> +/**
> +  Read a file.
> +
> +  @param FileName        The file to be read.
> +  @param BufferSize      The file buffer size
> +  @param Buffer          The file buffer
> +
> +  @retval EFI_SUCCESS    Read file successfully
> +  @retval EFI_NOT_FOUND  File not found
> +**/
> +EFI_STATUS
> +ReadFileToBuffer(
> +  IN  CHAR16                               *FileName,
> +  OUT UINTN                                *BufferSize,
> +  OUT VOID                                 **Buffer
> +  );
> +
> +extern UINTN  Argc;
> +extern CHAR16 *Argv[];
> +
> +/**
> +  Dump UX capsule information.
> +
> +  @param CapsuleHeader      The UX capsule header
> +**/
> +VOID
> +DumpUxCapsule(
> +  IN EFI_CAPSULE_HEADER  *CapsuleHeader
> +  )
> +{
> +  EFI_DISPLAY_CAPSULE                           *DisplayCapsule;
> +  DisplayCapsule = (EFI_DISPLAY_CAPSULE *)CapsuleHeader;
> +  Print(L"[UxCapusule]\n");
> +  Print(L"CapsuleHeader:\n");
> +  Print(L"  CapsuleGuid      - %g\n", &DisplayCapsule->CapsuleHeader.CapsuleGuid);
> +  Print(L"  HeaderSize       - 0x%x\n", DisplayCapsule->CapsuleHeader.HeaderSize);
> +  Print(L"  Flags            - 0x%x\n", DisplayCapsule->CapsuleHeader.Flags);
> +  Print(L"  CapsuleImageSize - 0x%x\n", DisplayCapsule-
> >CapsuleHeader.CapsuleImageSize);
> +  Print(L"ImagePayload:\n");
> +  Print(L"  Version          - 0x%x\n", DisplayCapsule->ImagePayload.Version);
> +  Print(L"  Checksum         - 0x%x\n", DisplayCapsule->ImagePayload.Checksum);
> +  Print(L"  ImageType        - 0x%x\n", DisplayCapsule->ImagePayload.ImageType);
> +  Print(L"  Mode             - 0x%x\n", DisplayCapsule->ImagePayload.Mode);
> +  Print(L"  OffsetX          - 0x%x\n", DisplayCapsule->ImagePayload.OffsetX);
> +  Print(L"  OffsetY          - 0x%x\n", DisplayCapsule->ImagePayload.OffsetY);
> +}
> +
> +/**
> +  Dump FMP image authentication information.
> +
> +  @param Image      The FMP capsule image
> +  @param ImageSize  The size of the FMP capsule image in bytes.
> +
> +  @return the size of FMP authentication.
> +**/
> +UINTN
> +DumpImageAuthentication(
> +  IN VOID   *Image,
> +  IN UINTN  ImageSize
> +  )
> +{
> +  EFI_FIRMWARE_IMAGE_AUTHENTICATION             *ImageAuthentication;
> +
> +  ImageAuthentication = Image;
> +  if (CompareGuid(&ImageAuthentication->AuthInfo.CertType, &gEfiCertPkcs7Guid) ||
> +      CompareGuid(&ImageAuthentication->AuthInfo.CertType,
> &gEfiCertTypeRsa2048Sha256Guid)) {
> +    Print(L"[ImageAuthentication]\n");
> +    Print(L"  MonotonicCount   - 0x%lx\n", ImageAuthentication->MonotonicCount);
> +    Print(L"WIN_CERTIFICATE:\n");
> +    Print(L"  dwLength         - 0x%x\n", ImageAuthentication->AuthInfo.Hdr.dwLength);
> +    Print(L"  wRevision        - 0x%x\n", ImageAuthentication-
> >AuthInfo.Hdr.wRevision);
> +    Print(L"  wCertificateType - 0x%x\n", ImageAuthentication-
> >AuthInfo.Hdr.wCertificateType);
> +    Print(L"  CertType         - %g\n", &ImageAuthentication->AuthInfo.CertType);
> +    return sizeof(ImageAuthentication->MonotonicCount) + ImageAuthentication-
> >AuthInfo.Hdr.dwLength;
> +  } else {
> +    return 0;
> +  }
> +}
> +
> +/**
> +  Dump EDKII system FMP capsule.
> +
> +  @param Image      The EDKII system FMP capsule.
> +  @param ImageSize  The size of the EDKII system FMP capsule in bytes.
> +**/
> +VOID
> +DumpEdkiiSystemFmpCapsule(
> +  IN VOID   *Image,
> +  IN UINTN  ImageSize
> +  )
> +{
> +  UINTN                                         ImageOffset;
> +  VOID                                          *BiosImage;
> +  UINTN                                         BiosImageSize;
> +  BOOLEAN                                       Result;
> +  EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR        *TempImageFmpInfo;
> +  EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR        *ImageFmpInfo;
> +  UINTN                                         ImageFmpInfoSize;
> +
> +  //
> +  // We do not know if there is EFI_FIRMWARE_IMAGE_AUTHENTICATION.
> +  // so just *try* to parse it
> +  //
> +  ImageOffset = DumpImageAuthentication(Image, ImageSize);
> +  Image = (UINT8 *)Image + ImageOffset;
> +  ImageSize -= ImageOffset;
> +  Print(L"[Image]\n");
> +  Print(L"  ImageSize   - 0x%x\n", ImageSize);
> +
> +  Result = ExtractConfigImage(Image, ImageSize, &BiosImage, &BiosImageSize);
> +  if (Result) {
> +    Print(L"  ConfigFileSize  - 0x%x\n", BiosImageSize);
> +  }
> +  Result = ExtractDriverFvImage(Image, ImageSize, &BiosImage, &BiosImageSize);
> +  if (Result) {
> +    Print(L"  DriverFvSize    - 0x%x\n", BiosImageSize);
> +  }
> +  Result = ExtractSystemFirmwareImage(Image, ImageSize, &BiosImage, &BiosImageSize);
> +  if (Result) {
> +    Print(L"  BiosImageSize   - 0x%x\n", BiosImageSize);
> +  }
> +  Result = ExtractSystemFirmwareImageFmpInfo(BiosImage, BiosImageSize,
> &TempImageFmpInfo, &ImageFmpInfoSize);
> +  if (Result) {
> +    ImageFmpInfo = AllocateCopyPool(ImageFmpInfoSize, TempImageFmpInfo);
> +    if (ImageFmpInfo != NULL) {
> +      Print(L"[ImageFmpInfo]\n");
> +      Print(L"  Signature                      - 0x%x\n", ImageFmpInfo->Signature);
> +      Print(L"  HeaderLength                   - 0x%x\n", ImageFmpInfo->HeaderLength);
> +      Print(L"  Length                         - 0x%x\n", ImageFmpInfo->Length);
> +      Print(L"  PackageVersion                 - 0x%x\n", ImageFmpInfo-
> >PackageVersion);
> +      Print(L"  PackageVersionNameStringOffset - 0x%x\n", ImageFmpInfo-
> >PackageVersionNameStringOffset);
> +      if (ImageFmpInfo->PackageVersionNameStringOffset != 0) {
> +        Print(L"                                 - %s\n", (UINT8 *)ImageFmpInfo +
> ImageFmpInfo->PackageVersionNameStringOffset);
> +      }
> +      Print(L"  ImageIndex                     - 0x%x\n", ImageFmpInfo->ImageIndex);
> +      Print(L"  ImageTypeId                    - %g\n", &ImageFmpInfo->ImageTypeId);
> +      Print(L"  ImageId                        - 0x%lx\n", ImageFmpInfo->ImageId);
> +      Print(L"  ImageIdNameStringOffset        - 0x%x\n", ImageFmpInfo-
> >ImageIdNameStringOffset);
> +      if (ImageFmpInfo->ImageIdNameStringOffset != 0) {
> +        Print(L"                                 - %s\n", (UINT8 *)ImageFmpInfo +
> ImageFmpInfo->ImageIdNameStringOffset);
> +      }
> +      Print(L"  Version                        - 0x%x\n", ImageFmpInfo->Version);
> +      Print(L"  VersionNameStringOffset        - 0x%x\n", ImageFmpInfo-
> >VersionNameStringOffset);
> +      if (ImageFmpInfo->VersionNameStringOffset != 0) {
> +        Print(L"                                 - %s\n", (UINT8 *)ImageFmpInfo +
> ImageFmpInfo->VersionNameStringOffset);
> +      }
> +      Print(L"  Size                           - 0x%lx\n", ImageFmpInfo->Size);
> +      Print(L"  AttributesSupported            - 0x%lx\n", ImageFmpInfo-
> >AttributesSupported);
> +      Print(L"  AttributesSetting              - 0x%lx\n", ImageFmpInfo-
> >AttributesSetting);
> +      Print(L"  Compatibilities                - 0x%lx\n", ImageFmpInfo-
> >Compatibilities);
> +      Print(L"  LowestSupportedImageVersion    - 0x%x\n", ImageFmpInfo-
> >LowestSupportedImageVersion);
> +      Print(L"  LastAttemptVersion             - 0x%x\n", ImageFmpInfo-
> >LastAttemptVersion);
> +      Print(L"  LastAttemptStatus              - 0x%x\n", ImageFmpInfo-
> >LastAttemptStatus);
> +      Print(L"  HardwareInstance               - 0x%lx\n", ImageFmpInfo-
> >HardwareInstance);
> +      Print(L"  Version                        - 0x%x\n", ImageFmpInfo->Version);
> +      FreePool(ImageFmpInfo);
> +    }
> +  }
> +}
> +
> +/**
> +  Dump a non-nested FMP capsule.
> +
> +  @param  CapsuleHeader  A pointer to CapsuleHeader
> +  @param  IsSystemFmp    If it is a system FMP
> +**/
> +VOID
> +DumpFmpCapsule(
> +  IN EFI_CAPSULE_HEADER  *CapsuleHeader,
> +  IN BOOLEAN             IsSystemFmp
> +  )
> +{
> +  EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER        *FmpCapsuleHeader;
> +  UINT64                                        *ItemOffsetList;
> +  UINTN                                         Index;
> +  UINTN                                         Count;
> +  EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER  *FmpImageHeader;
> +  VOID                                          *Image;
> +
> +  Print(L"[FmpCapusule]\n");
> +  Print(L"CapsuleHeader:\n");
> +  Print(L"  CapsuleGuid      - %g\n", &CapsuleHeader->CapsuleGuid);
> +  Print(L"  HeaderSize       - 0x%x\n", CapsuleHeader->HeaderSize);
> +  Print(L"  Flags            - 0x%x\n", CapsuleHeader->Flags);
> +  Print(L"  CapsuleImageSize - 0x%x\n", CapsuleHeader->CapsuleImageSize);
> +
> +  FmpCapsuleHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *)((UINT8 *)CapsuleHeader
> + CapsuleHeader->HeaderSize);
> +  ItemOffsetList = (UINT64 *)(FmpCapsuleHeader + 1);
> +  Print(L"FmpHeader:\n");
> +  Print(L"  Version             - 0x%x\n", FmpCapsuleHeader->Version);
> +  Print(L"  EmbeddedDriverCount - 0x%x\n", FmpCapsuleHeader->EmbeddedDriverCount);
> +  Print(L"  PayloadItemCount    - 0x%x\n", FmpCapsuleHeader->PayloadItemCount);
> +  Count = FmpCapsuleHeader->EmbeddedDriverCount + FmpCapsuleHeader->PayloadItemCount;
> +  for (Index = 0; Index < Count; Index++) {
> +    Print(L"  Offset[%d]           - 0x%x\n", Index, ItemOffsetList[Index]);
> +  }
> +
> +  for (Index = FmpCapsuleHeader->EmbeddedDriverCount; Index < Count; Index++) {
> +    Print(L"FmpPayload[%d] ImageHeader:\n", Index);
> +    FmpImageHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *)((UINT8
> *)FmpCapsuleHeader + ItemOffsetList[Index]);
> +    Print(L"  Version                - 0x%x\n", FmpImageHeader->Version);
> +    Print(L"  UpdateImageTypeId      - %g\n", &FmpImageHeader->UpdateImageTypeId);
> +    Print(L"  UpdateImageIndex       - 0x%x\n", FmpImageHeader->UpdateImageIndex);
> +    Print(L"  UpdateImageSize        - 0x%x\n", FmpImageHeader->UpdateImageSize);
> +    Print(L"  UpdateVendorCodeSize   - 0x%x\n", FmpImageHeader->UpdateVendorCodeSize);
> +    if (FmpImageHeader->Version >=
> EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {
> +      Print(L"  UpdateHardwareInstance - 0x%lx\n", FmpImageHeader-
> >UpdateHardwareInstance);
> +    }
> +    if (FmpImageHeader->Version >=
> EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {
> +      Image = (UINT8 *)(FmpImageHeader + 1);
> +    }  else {
> +      Image = (UINT8 *)FmpImageHeader +
> OFFSET_OF(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER, UpdateHardwareInstance);
> +    }
> +    if (IsSystemFmp) {
> +      DumpEdkiiSystemFmpCapsule(Image, FmpImageHeader->UpdateImageSize);
> +    }
> +  }
> +}
> +
> +/**
> +  Return if there is a FMP header below capsule header.
> +
> +  @param[in] CapsuleHeader A pointer to EFI_CAPSULE_HEADER
> +
> +  @retval TRUE  There is a FMP header below capsule header.
> +  @retval FALSE There is not a FMP header below capsule header
> +**/
> +BOOLEAN
> +IsNestedFmpCapsule(
> +  IN EFI_CAPSULE_HEADER         *CapsuleHeader
> +  )
> +{
> +  EFI_STATUS                 Status;
> +  EFI_SYSTEM_RESOURCE_TABLE  *Esrt;
> +  EFI_SYSTEM_RESOURCE_ENTRY  *EsrtEntry;
> +  UINTN                      Index;
> +  BOOLEAN                    EsrtGuidFound;
> +  EFI_CAPSULE_HEADER         *NestedCapsuleHeader;
> +  UINTN                      NestedCapsuleSize;
> +
> +  //
> +  // Check ESRT
> +  //
> +  EsrtGuidFound = FALSE;
> +  Status = EfiGetSystemConfigurationTable(&gEfiSystemResourceTableGuid, (VOID
> **)&Esrt);
> +  if (!EFI_ERROR(Status)) {
> +    EsrtEntry = (VOID *)(Esrt + 1);
> +    for (Index = 0; Index < Esrt->FwResourceCount; Index++, EsrtEntry++) {
> +      if (CompareGuid(&EsrtEntry->FwClass, &CapsuleHeader->CapsuleGuid)) {
> +        EsrtGuidFound = TRUE;
> +        break;
> +      }
> +    }
> +  }
> +
> +  if (!EsrtGuidFound) {
> +    return FALSE;
> +  }
> +
> +  //
> +  // Check nested capsule header
> +  // FMP GUID after ESRT one
> +  //
> +  NestedCapsuleHeader = (EFI_CAPSULE_HEADER *)((UINT8 *)CapsuleHeader + CapsuleHeader-
> >HeaderSize);
> +  NestedCapsuleSize = (UINTN)CapsuleHeader + CapsuleHeader->HeaderSize -
> (UINTN)NestedCapsuleHeader;
> +  if (NestedCapsuleSize < sizeof(EFI_CAPSULE_HEADER)) {
> +    return FALSE;
> +  }
> +  if (!CompareGuid(&NestedCapsuleHeader->CapsuleGuid, &gEfiFmpCapsuleGuid)) {
> +    return FALSE;
> +  }
> +  return TRUE;
> +}
> +
> +/**
> +  Dump capsule information
> +
> +  @retval EFI_SUCCESS            The capsule information is dumped.
> +  @retval EFI_UNSUPPORTED        Input parameter is not valid.
> +**/
> +EFI_STATUS
> +DumpCapsule(
> +  VOID
> +  )
> +{
> +  CHAR16                                        *CapsuleName;
> +  VOID                                          *Buffer;
> +  UINTN                                         FileSize;
> +  BOOLEAN                                       IsSystemFmp;
> +  EFI_CAPSULE_HEADER                            *CapsuleHeader;
> +  EFI_STATUS                                    Status;
> +
> +  if (Argc != 3) {
> +    Print(L"CapsuleApp: Invalid Parameter.\n");
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  IsSystemFmp = FALSE;
> +  if (StrCmp(Argv[1], L"-DS") == 0) {
> +    IsSystemFmp = TRUE;
> +  }
> +
> +  CapsuleName = Argv[2];
> +  Status = ReadFileToBuffer(CapsuleName, &FileSize, &Buffer);
> +  if (EFI_ERROR(Status)) {
> +    Print(L"CapsuleApp: Capsule (%s) is not found.\n", CapsuleName);
> +    goto Done;
> +  }
> +
> +  CapsuleHeader = Buffer;
> +  if (CompareGuid(&CapsuleHeader->CapsuleGuid, &gWindowsUxCapsuleGuid)) {
> +    DumpUxCapsule(CapsuleHeader);
> +    Status = EFI_SUCCESS;
> +    goto Done;
> +  }
> +
> +  if (CompareGuid(&CapsuleHeader->CapsuleGuid, &gEfiFmpCapsuleGuid)) {
> +    DumpFmpCapsule(CapsuleHeader, IsSystemFmp);
> +  }
> +  if (IsNestedFmpCapsule(CapsuleHeader)) {
> +    Print(L"[NestedCapusule]\n");
> +    Print(L"CapsuleHeader:\n");
> +    Print(L"  CapsuleGuid      - %g\n", &CapsuleHeader->CapsuleGuid);
> +    Print(L"  HeaderSize       - 0x%x\n", CapsuleHeader->HeaderSize);
> +    Print(L"  Flags            - 0x%x\n", CapsuleHeader->Flags);
> +    Print(L"  CapsuleImageSize - 0x%x\n", CapsuleHeader->CapsuleImageSize);
> +    DumpFmpCapsule((EFI_CAPSULE_HEADER *)((UINTN)CapsuleHeader + CapsuleHeader-
> >HeaderSize), IsSystemFmp);
> +  }
> +
> +Done:
> +  FreePool(Buffer);
> +  return Status;
> +}
> +
> +/**
> +  Dump capsule status variable.
> +
> +  @retval EFI_SUCCESS            The capsule status variable is dumped.
> +  @retval EFI_UNSUPPORTED        Input parameter is not valid.
> +**/
> +EFI_STATUS
> +DmpCapsuleStatusVariable(
> +  VOID
> +  )
> +{
> +  EFI_STATUS                          Status;
> +  UINT32                              Index;
> +  CHAR16                              CapsuleVarName[20];
> +  CHAR16                              *TempVarName;
> +  EFI_CAPSULE_RESULT_VARIABLE_HEADER  *CapsuleResult;
> +  EFI_CAPSULE_RESULT_VARIABLE_FMP     *CapsuleResultFmp;
> +  UINTN                               CapsuleFileNameSize;
> +  CHAR16                              CapsuleIndexData[12];
> +  CHAR16                              *CapsuleIndex;
> +
> +  Status = GetVariable2(
> +             L"CapsuleMax",
> +             &gEfiCapsuleReportGuid,
> +             (VOID **)&CapsuleIndex,
> +             NULL
> +             );
> +  if (!EFI_ERROR(Status)) {
> +    CopyMem(CapsuleIndexData, CapsuleIndex, 11 * sizeof(CHAR16));
> +    CapsuleIndexData[11] = 0;
> +    Print(L"CapsuleMax - %s\n", CapsuleIndexData);
> +    FreePool(CapsuleIndex);
> +  }
> +  Status = GetVariable2(
> +             L"CapsuleLast",
> +             &gEfiCapsuleReportGuid,
> +             (VOID **)&CapsuleIndex,
> +             NULL
> +             );
> +  if (!EFI_ERROR(Status)) {
> +    CopyMem(CapsuleIndexData, CapsuleIndex, 11 * sizeof(CHAR16));
> +    CapsuleIndexData[11] = 0;
> +    Print(L"CapsuleLast - %s\n", CapsuleIndexData);
> +    FreePool(CapsuleIndex);
> +  }
> +
> +
> +  StrCpyS (CapsuleVarName, sizeof(CapsuleVarName)/sizeof(CapsuleVarName[0]),
> L"Capsule");
> +  TempVarName = CapsuleVarName + StrLen (CapsuleVarName);
> +  Index = 0;
> +
> +  while (TRUE) {
> +    UnicodeSPrint (TempVarName, 5 * sizeof(CHAR16), L"%04x", Index);
> +
> +    Status = GetVariable2 (
> +               CapsuleVarName,
> +               &gEfiCapsuleReportGuid,
> +               (VOID **) &CapsuleResult,
> +               NULL
> +               );
> +    if (Status == EFI_NOT_FOUND) {
> +      break;
> +    } else if (EFI_ERROR(Status)) {
> +      continue;
> +    }
> +
> +    //
> +    // display capsule process status
> +    //
> +    if (CapsuleResult->VariableTotalSize >=
> sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER)) {
> +      Print (L"CapsuleName: %s\n", CapsuleVarName);
> +      Print (L"  Capsule Guid: %g\n", &CapsuleResult->CapsuleGuid);
> +      Print (L"  Capsule ProcessedTime: %t\n", &CapsuleResult->CapsuleProcessed);
> +      Print (L"  Capsule Status: %r\n", CapsuleResult->CapsuleStatus);
> +    }
> +
> +    if (CompareGuid(&CapsuleResult->CapsuleGuid, &gEfiFmpCapsuleGuid)) {
> +      if (CapsuleResult->VariableTotalSize >=
> sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER) + sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP)) {
> +        CapsuleResultFmp = (EFI_CAPSULE_RESULT_VARIABLE_FMP *)(CapsuleResult + 1);
> +        Print(L"  Capsule FMP Version: 0x%x\n", CapsuleResultFmp->Version);
> +        Print(L"  Capsule FMP PayloadIndex: 0x%x\n", CapsuleResultFmp->PayloadIndex);
> +        Print(L"  Capsule FMP UpdateImageIndex: 0x%x\n", CapsuleResultFmp-
> >UpdateImageIndex);
> +        Print(L"  Capsule FMP UpdateImageTypeId: %g\n", &CapsuleResultFmp-
> >UpdateImageTypeId);
> +        if (CapsuleResult->VariableTotalSize >
> sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER) + sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP)) {
> +          Print(L"  Capsule FMP CapsuleFileName: %s\n", (CapsuleResultFmp + 1));
> +          CapsuleFileNameSize = StrSize((CHAR16 *)(CapsuleResultFmp + 1));
> +          if (CapsuleResult->VariableTotalSize >
> sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER) + sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP) +
> CapsuleFileNameSize) {
> +            Print(L"  Capsule FMP CapsuleTarget: %s\n", (UINT8 *)(CapsuleResultFmp +
> 1) + CapsuleFileNameSize);
> +          }
> +        }
> +      }
> +    }
> +
> +    FreePool(CapsuleResult);
> +
> +    Index++;
> +    if (Index > 0xFFFF) {
> +      break;
> +    }
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +CHAR8 *mFwTypeString[] = {
> +  "Unknown",
> +  "SystemFirmware",
> +  "DeviceFirmware",
> +  "UefiDriver",
> +};
> +
> +CHAR8 *mLastAttemptStatusString[] = {
> +  "Success",
> +  "Error: Unsuccessful",
> +  "Error: Insufficient Resources",
> +  "Error: Incorrect Version",
> +  "Error: Invalid Format",
> +  "Error: Auth Error",
> +  "Error: Power Event AC",
> +  "Error: Power Event Battery",
> +};
> +
> +/**
> +  Convert FwType to a string.
> +
> +  @param FwType  FwType in ESRT
> +
> +  @return a string for FwType.
> +**/
> +CHAR8 *
> +FwTypeToString(
> +  IN UINT32 FwType
> +  )
> +{
> +  if (FwType < sizeof(mFwTypeString) / sizeof(mFwTypeString[0])) {
> +    return mFwTypeString[FwType];
> +  } else {
> +    return "Invalid";
> +  }
> +}
> +
> +/**
> +  Convert LastAttemptStatus to a string.
> +
> +  @param LastAttemptStatus  LastAttemptStatus in FMP or ESRT
> +
> +  @return a string for LastAttemptStatus.
> +**/
> +CHAR8 *
> +LastAttemptStatusToString(
> +  IN UINT32 LastAttemptStatus
> +  )
> +{
> +  if (LastAttemptStatus < sizeof(mLastAttemptStatusString) /
> sizeof(mLastAttemptStatusString[0])) {
> +    return mLastAttemptStatusString[LastAttemptStatus];
> +  } else {
> +    return "Error: Unknown";
> +  }
> +}
> +
> +/**
> +  Dump ESRT entry.
> +
> +  @param EsrtEntry  ESRT entry
> +**/
> +VOID
> +DumpEsrtEntry(
> +  IN EFI_SYSTEM_RESOURCE_ENTRY  *EsrtEntry
> +  )
> +{
> +  Print(L"  FwClass                  - %g\n", &EsrtEntry->FwClass);
> +  Print(L"  FwType                   - 0x%x (%a)\n", EsrtEntry->FwType,
> FwTypeToString(EsrtEntry->FwType));
> +  Print(L"  FwVersion                - 0x%x\n", EsrtEntry->FwVersion);
> +  Print(L"  LowestSupportedFwVersion - 0x%x\n", EsrtEntry->LowestSupportedFwVersion);
> +  Print(L"  CapsuleFlags             - 0x%x\n", EsrtEntry->CapsuleFlags);
> +  Print(L"    PERSIST_ACROSS_RESET   - 0x%x\n", EsrtEntry->CapsuleFlags &
> CAPSULE_FLAGS_PERSIST_ACROSS_RESET);
> +  Print(L"    POPULATE_SYSTEM_TABLE  - 0x%x\n", EsrtEntry->CapsuleFlags &
> CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE);
> +  Print(L"    INITIATE_RESET         - 0x%x\n", EsrtEntry->CapsuleFlags &
> CAPSULE_FLAGS_INITIATE_RESET);
> +  Print(L"  LastAttemptVersion       - 0x%x\n", EsrtEntry->LastAttemptVersion);
> +  Print(L"  LastAttemptStatus        - 0x%x (%a)\n", EsrtEntry->LastAttemptStatus,
> LastAttemptStatusToString(EsrtEntry->LastAttemptStatus));
> +}
> +
> +/**
> +  Dump ESRT table.
> +
> +  @param Esrt  ESRT table
> +**/
> +VOID
> +DumpEsrt(
> +  IN EFI_SYSTEM_RESOURCE_TABLE  *Esrt
> +  )
> +{
> +  UINTN                      Index;
> +  EFI_SYSTEM_RESOURCE_ENTRY  *EsrtEntry;
> +
> +  Print(L"EFI_SYSTEM_RESOURCE_TABLE:\n");
> +  Print(L"FwResourceCount    - 0x%x\n", Esrt->FwResourceCount);
> +  Print(L"FwResourceCountMax - 0x%x\n", Esrt->FwResourceCountMax);
> +  Print(L"FwResourceVersion  - 0x%lx\n", Esrt->FwResourceVersion);
> +
> +  EsrtEntry = (VOID *)(Esrt + 1);
> +  for (Index = 0; Index < Esrt->FwResourceCount; Index++) {
> +    Print(L"EFI_SYSTEM_RESOURCE_ENTRY (%d):\n", Index);
> +    DumpEsrtEntry(EsrtEntry);
> +    EsrtEntry++;
> +  }
> +}
> +
> +/**
> +  Dump ESRT info.
> +**/
> +VOID
> +DumpEsrtData (
> +  VOID
> +  )
> +{
> +  EFI_STATUS                 Status;
> +  EFI_SYSTEM_RESOURCE_TABLE  *Esrt;
> +
> +  Print(L"##############\n");
> +  Print(L"# ESRT TABLE #\n");
> +  Print(L"##############\n");
> +
> +  Status = EfiGetSystemConfigurationTable (&gEfiSystemResourceTableGuid, (VOID
> **)&Esrt);
> +  if (EFI_ERROR(Status)) {
> +    Print(L"ESRT - %r\n", Status);
> +    return;
> +  }
> +  DumpEsrt(Esrt);
> +  Print(L"\n");
> +}
> +
> +/**
> +  Dump FMP information.
> +
> +  @param ImageInfoSize       The size of ImageInfo, in bytes.
> +  @param ImageInfo           A pointer to EFI_FIRMWARE_IMAGE_DESCRIPTOR.
> +  @param DescriptorVersion   The version of EFI_FIRMWARE_IMAGE_DESCRIPTOR.
> +  @param DescriptorCount     The count of EFI_FIRMWARE_IMAGE_DESCRIPTOR.
> +  @param DescriptorSize      The size of an individual EFI_FIRMWARE_IMAGE_DESCRIPTOR,
> in bytes.
> +  @param PackageVersion      The version of package.
> +  @param PackageVersionName  The version name of package.
> +**/
> +VOID
> +DumpFmpImageInfo(
> +  IN UINTN                           ImageInfoSize,
> +  IN EFI_FIRMWARE_IMAGE_DESCRIPTOR   *ImageInfo,
> +  IN UINT32                          DescriptorVersion,
> +  IN UINT8                           DescriptorCount,
> +  IN UINTN                           DescriptorSize,
> +  IN UINT32                          PackageVersion,
> +  IN CHAR16                          *PackageVersionName
> +  )
> +{
> +  EFI_FIRMWARE_IMAGE_DESCRIPTOR                 *CurrentImageInfo;
> +  UINTN                                         Index;
> +
> +  Print(L"  DescriptorVersion  - 0x%x\n", DescriptorVersion);
> +  Print(L"  DescriptorCount    - 0x%x\n", DescriptorCount);
> +  Print(L"  DescriptorSize     - 0x%x\n", DescriptorSize);
> +  Print(L"  PackageVersion     - 0x%x\n", PackageVersion);
> +  Print(L"  PackageVersionName - \"%s\"\n", PackageVersionName);
> +  CurrentImageInfo = ImageInfo;
> +  for (Index = 0; Index < DescriptorCount; Index++) {
> +    Print(L"  ImageDescriptor (%d)\n", Index);
> +    Print(L"    ImageIndex                  - 0x%x\n", CurrentImageInfo->ImageIndex);
> +    Print(L"    ImageTypeId                 - %g\n", &CurrentImageInfo->ImageTypeId);
> +    Print(L"    ImageId                     - 0x%lx\n", CurrentImageInfo->ImageId);
> +    Print(L"    ImageIdName                 - \"%s\"\n", CurrentImageInfo-
> >ImageIdName);
> +    Print(L"    Version                     - 0x%x\n", CurrentImageInfo->Version);
> +    Print(L"    VersionName                 - \"%s\"\n", CurrentImageInfo-
> >VersionName);
> +    Print(L"    Size                        - 0x%x\n", CurrentImageInfo->Size);
> +    Print(L"    AttributesSupported         - 0x%lx\n", CurrentImageInfo-
> >AttributesSupported);
> +    Print(L"      IMAGE_UPDATABLE           - 0x%lx\n", CurrentImageInfo-
> >AttributesSupported & IMAGE_ATTRIBUTE_IMAGE_UPDATABLE);
> +    Print(L"      RESET_REQUIRED            - 0x%lx\n", CurrentImageInfo-
> >AttributesSupported & IMAGE_ATTRIBUTE_RESET_REQUIRED);
> +    Print(L"      AUTHENTICATION_REQUIRED   - 0x%lx\n", CurrentImageInfo-
> >AttributesSupported & IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);
> +    Print(L"      IN_USE                    - 0x%lx\n", CurrentImageInfo-
> >AttributesSupported & IMAGE_ATTRIBUTE_IN_USE);
> +    Print(L"      UEFI_IMAGE                - 0x%lx\n", CurrentImageInfo-
> >AttributesSupported & IMAGE_ATTRIBUTE_UEFI_IMAGE);
> +    Print(L"    AttributesSetting           - 0x%lx\n", CurrentImageInfo-
> >AttributesSetting);
> +    Print(L"      IMAGE_UPDATABLE           - 0x%lx\n", CurrentImageInfo-
> >AttributesSetting & IMAGE_ATTRIBUTE_IMAGE_UPDATABLE);
> +    Print(L"      RESET_REQUIRED            - 0x%lx\n", CurrentImageInfo-
> >AttributesSetting & IMAGE_ATTRIBUTE_RESET_REQUIRED);
> +    Print(L"      AUTHENTICATION_REQUIRED   - 0x%lx\n", CurrentImageInfo-
> >AttributesSetting & IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);
> +    Print(L"      IN_USE                    - 0x%lx\n", CurrentImageInfo-
> >AttributesSetting & IMAGE_ATTRIBUTE_IN_USE);
> +    Print(L"      UEFI_IMAGE                - 0x%lx\n", CurrentImageInfo-
> >AttributesSetting & IMAGE_ATTRIBUTE_UEFI_IMAGE);
> +    Print(L"    Compatibilities             - 0x%lx\n", CurrentImageInfo-
> >Compatibilities);
> +    Print(L"      COMPATIB_CHECK_SUPPORTED  - 0x%lx\n", CurrentImageInfo-
> >Compatibilities & IMAGE_COMPATIBILITY_CHECK_SUPPORTED);
> +    if (DescriptorVersion > 1) {
> +      Print(L"    LowestSupportedImageVersion - 0x%x\n", CurrentImageInfo-
> >LowestSupportedImageVersion);
> +      if (DescriptorVersion > 2) {
> +        Print(L"    LastAttemptVersion          - 0x%x\n", CurrentImageInfo-
> >LastAttemptVersion);
> +        Print(L"    LastAttemptStatus           - 0x%x (%a)\n", CurrentImageInfo-
> >LastAttemptStatus, LastAttemptStatusToString(CurrentImageInfo->LastAttemptStatus));
> +        Print(L"    HardwareInstance            - 0x%lx\n", CurrentImageInfo-
> >HardwareInstance);
> +      }
> +    }
> +    //
> +    // Use DescriptorSize to move ImageInfo Pointer to stay compatible with different
> ImageInfo version
> +    //
> +    CurrentImageInfo = (EFI_FIRMWARE_IMAGE_DESCRIPTOR *)((UINT8 *)CurrentImageInfo +
> DescriptorSize);
> +  }
> +}
> +
> +/**
> +  Dump FMP package information.
> +
> +  @param PackageVersion             The version of package.
> +  @param PackageVersionName         The version name of package.
> +  @param PackageVersionNameMaxLen   The maximum length of PackageVersionName.
> +  @param AttributesSupported        Package attributes that are supported by this
> device.
> +  @param AttributesSetting          Package attributes.
> +**/
> +VOID
> +DumpFmpPackageInfo(
> +  IN UINT32                           PackageVersion,
> +  IN CHAR16                           *PackageVersionName,
> +  IN UINT32                           PackageVersionNameMaxLen,
> +  IN UINT64                           AttributesSupported,
> +  IN UINT64                           AttributesSetting
> +  )
> +{
> +  Print(L"  PackageVersion              - 0x%x\n", PackageVersion);
> +  Print(L"  PackageVersionName          - \"%s\"\n", PackageVersionName);
> +  Print(L"  PackageVersionNameMaxLen    - 0x%x\n", PackageVersionNameMaxLen);
> +  Print(L"  AttributesSupported         - 0x%lx\n", AttributesSupported);
> +  Print(L"    IMAGE_UPDATABLE           - 0x%lx\n", AttributesSupported &
> IMAGE_ATTRIBUTE_IMAGE_UPDATABLE);
> +  Print(L"    RESET_REQUIRED            - 0x%lx\n", AttributesSupported &
> IMAGE_ATTRIBUTE_RESET_REQUIRED);
> +  Print(L"    AUTHENTICATION_REQUIRED   - 0x%lx\n", AttributesSupported &
> IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);
> +  Print(L"  AttributesSetting           - 0x%lx\n", AttributesSetting);
> +  Print(L"    IMAGE_UPDATABLE           - 0x%lx\n", AttributesSetting &
> IMAGE_ATTRIBUTE_IMAGE_UPDATABLE);
> +  Print(L"    RESET_REQUIRED            - 0x%lx\n", AttributesSetting &
> IMAGE_ATTRIBUTE_RESET_REQUIRED);
> +  Print(L"    AUTHENTICATION_REQUIRED   - 0x%lx\n", AttributesSetting &
> IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);
> +}
> +
> +/**
> +  Dump FMP protocol info.
> +**/
> +VOID
> +DumpFmpData (
> +  VOID
> +  )
> +{
> +  EFI_STATUS                                    Status;
> +  EFI_FIRMWARE_MANAGEMENT_PROTOCOL              *Fmp;
> +  EFI_HANDLE                                    *HandleBuffer;
> +  UINTN                                         NumberOfHandles;
> +  UINTN                                         Index;
> +  EFI_FIRMWARE_IMAGE_DESCRIPTOR                 *FmpImageInfoBuf;
> +  UINTN                                         ImageInfoSize;
> +  UINT32                                        FmpImageInfoDescriptorVer;
> +  UINT8                                         FmpImageInfoCount;
> +  UINTN                                         DescriptorSize;
> +  UINT32                                        PackageVersion;
> +  CHAR16                                        *PackageVersionName;
> +  UINT32                                        PackageVersionNameMaxLen;
> +  UINT64                                        AttributesSupported;
> +  UINT64                                        AttributesSetting;
> +
> +  Print(L"############\n");
> +  Print(L"# FMP DATA #\n");
> +  Print(L"############\n");
> +  Status = gBS->LocateHandleBuffer (
> +                  ByProtocol,
> +                  &gEfiFirmwareManagementProtocolGuid,
> +                  NULL,
> +                  &NumberOfHandles,
> +                  &HandleBuffer
> +                  );
> +  if (EFI_ERROR(Status)) {
> +    Print(L"FMP protocol - %r\n", EFI_NOT_FOUND);
> +    return;
> +  }
> +
> +  for (Index = 0; Index < NumberOfHandles; Index++) {
> +    Status = gBS->HandleProtocol(
> +                    HandleBuffer[Index],
> +                    &gEfiFirmwareManagementProtocolGuid,
> +                    (VOID **)&Fmp
> +                    );
> +    if (EFI_ERROR(Status)) {
> +      continue;
> +    }
> +
> +    ImageInfoSize = 0;
> +    Status = Fmp->GetImageInfo (
> +                    Fmp,
> +                    &ImageInfoSize,
> +                    NULL,
> +                    NULL,
> +                    NULL,
> +                    NULL,
> +                    NULL,
> +                    NULL
> +                    );
> +    if (Status != EFI_BUFFER_TOO_SMALL) {
> +      continue;
> +    }
> +
> +    FmpImageInfoBuf = NULL;
> +    FmpImageInfoBuf = AllocateZeroPool (ImageInfoSize);
> +    if (FmpImageInfoBuf == NULL) {
> +      Status = EFI_OUT_OF_RESOURCES;
> +      goto EXIT;
> +    }
> +
> +    PackageVersionName = NULL;
> +    Status = Fmp->GetImageInfo (
> +                    Fmp,
> +                    &ImageInfoSize,               // ImageInfoSize
> +                    FmpImageInfoBuf,              // ImageInfo
> +                    &FmpImageInfoDescriptorVer,   // DescriptorVersion
> +                    &FmpImageInfoCount,           // DescriptorCount
> +                    &DescriptorSize,              // DescriptorSize
> +                    &PackageVersion,              // PackageVersion
> +                    &PackageVersionName           // PackageVersionName
> +                    );
> +
> +    //
> +    // If FMP GetInformation interface failed, skip this resource
> +    //
> +    if (EFI_ERROR(Status)) {
> +      Print(L"FMP (%d) ImageInfo - %r\n", Index, Status);
> +      FreePool(FmpImageInfoBuf);
> +      continue;
> +    }
> +
> +    Print(L"FMP (%d) ImageInfo:\n", Index);
> +    DumpFmpImageInfo(
> +      ImageInfoSize,               // ImageInfoSize
> +      FmpImageInfoBuf,             // ImageInfo
> +      FmpImageInfoDescriptorVer,   // DescriptorVersion
> +      FmpImageInfoCount,           // DescriptorCount
> +      DescriptorSize,              // DescriptorSize
> +      PackageVersion,              // PackageVersion
> +      PackageVersionName           // PackageVersionName
> +      );
> +
> +    if (PackageVersionName != NULL) {
> +      FreePool(PackageVersionName);
> +    }
> +    FreePool(FmpImageInfoBuf);
> +
> +    //
> +    // Get package info
> +    //
> +    PackageVersionName = NULL;
> +    Status = Fmp->GetPackageInfo (
> +                    Fmp,
> +                    &PackageVersion,              // PackageVersion
> +                    &PackageVersionName,          // PackageVersionName
> +                    &PackageVersionNameMaxLen,    // PackageVersionNameMaxLen
> +                    &AttributesSupported,         // AttributesSupported
> +                    &AttributesSetting            // AttributesSetting
> +                    );
> +    if (EFI_ERROR(Status)) {
> +      Print(L"FMP (%d) PackageInfo - %r\n", Index, Status);
> +    } else {
> +      Print(L"FMP (%d) ImageInfo:\n", Index);
> +      DumpFmpPackageInfo(
> +        PackageVersion,              // PackageVersion
> +        PackageVersionName,          // PackageVersionName
> +        PackageVersionNameMaxLen,    // PackageVersionNameMaxLen
> +        AttributesSupported,         // AttributesSupported
> +        AttributesSetting            // AttributesSetting
> +        );
> +
> +      if (PackageVersionName != NULL) {
> +        FreePool(PackageVersionName);
> +      }
> +    }
> +  }
> +  Print(L"\n");
> +
> +EXIT:
> +  FreePool(HandleBuffer);
> +}
> --
> 2.7.4.windows.1



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

* Re: [PATCH 37/45] QuarkPlatformPkg/dsc/fdf: add capsule generation DSC/FDF.
  2016-09-29  1:01   ` Kinney, Michael D
@ 2016-09-29  2:33     ` Yao, Jiewen
  0 siblings, 0 replies; 83+ messages in thread
From: Yao, Jiewen @ 2016-09-29  2:33 UTC (permalink / raw)
  To: Kinney, Michael D, edk2-devel@lists.01.org
  Cc: Steele, Kelly, Tian, Feng, Zeng, Star, Gao, Liming, Zhang, Chao B

Hi Mike
Yes you are right. This is a work-around for current tool limitation.
We can remove such limitation after the tool has solution.

I will update the recovery file name to make it more readable.

Thank you
Yao Jiewen

From: Kinney, Michael D
Sent: Thursday, September 29, 2016 9:01 AM
To: Yao, Jiewen <jiewen.yao@intel.com>; edk2-devel@lists.01.org; Kinney, Michael D <michael.d.kinney@intel.com>
Cc: Steele, Kelly <kelly.steele@intel.com>; Tian, Feng <feng.tian@intel.com>; Zeng, Star <star.zeng@intel.com>; Gao, Liming <liming.gao@intel.com>; Zhang, Chao B <chao.b.zhang@intel.com>
Subject: RE: [PATCH 37/45] QuarkPlatformPkg/dsc/fdf: add capsule generation DSC/FDF.

Jiewen,

This DSC/FDF generates a build failure for me from GenFds.
I have entered a BaseTools bug into Bugzilla

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

There is a workaround to create the file that is missing
GenFds can work, so I was able to generate a Capsule
Image for FW update and saw it work.

My other major feedback on this DSC/FDF file is why this
Content was not added to Quark DSC/FDF with #ifdef for
RECOVERY_ENABLE and CAPSULE_ENABLE flags?

Is the [Capsule.BiosCapsuleFmpRsa2048] section really
the recovery image?  Can we use Recovery in the name
instead of Capsule?

Thanks,

Mike

> -----Original Message-----
> From: Yao, Jiewen
> Sent: Tuesday, September 20, 2016 11:45 PM
> To: edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>
> Cc: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>; Steele, Kelly
> <kelly.steele@intel.com<mailto:kelly.steele@intel.com>>; Tian, Feng <feng.tian@intel.com<mailto:feng.tian@intel.com>>; Zeng, Star
> <star.zeng@intel.com<mailto:star.zeng@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: [PATCH 37/45] QuarkPlatformPkg/dsc/fdf: add capsule generation DSC/FDF.
>
> Add DSC/FDF to generate capsule image.
> It is separated from normal DSC/FDF, because the FDF file need use
> the result of final build.
>
> Cc: Michael D Kinney <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>
> Cc: Kelly Steele <kelly.steele@intel.com<mailto:kelly.steele@intel.com>>
> Cc: Feng Tian <feng.tian@intel.com<mailto:feng.tian@intel.com>>
> Cc: Star Zeng <star.zeng@intel.com<mailto:star.zeng@intel.com>>
> Cc: Liming Gao <liming.gao@intel.com<mailto:liming.gao@intel.com>>
> Cc: Chao Zhang <chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com>>
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Jiewen Yao <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>
> ---
>  QuarkPlatformPkg/QuarkCapsule.dsc | 44 +++++++++++
>  QuarkPlatformPkg/QuarkCapsule.fdf | 82 ++++++++++++++++++++
>  2 files changed, 126 insertions(+)
>
> diff --git a/QuarkPlatformPkg/QuarkCapsule.dsc b/QuarkPlatformPkg/QuarkCapsule.dsc
> new file mode 100644
> index 0000000..3785cbd
> --- /dev/null
> +++ b/QuarkPlatformPkg/QuarkCapsule.dsc
> @@ -0,0 +1,44 @@
> +## @file
> +# Clanton Peak CRB platform with 32-bit DXE for 4MB/8MB flash devices.
> +#
> +# This package provides Clanton Peak CRB platform specific capsule.
> +# Copyright (c) 2016 Intel Corporation.
> +#
> +# This program and the accompanying materials
> +# are licensed and made available under the terms and conditions of the BSD License
> +# which accompanies this distribution.  The full text of the license may be found at
> +# http://opensource.org/licenses/bsd-license.php
> +#
> +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +#
> +##
> +
> +[Defines]
> +  PLATFORM_NAME                  = Quark
> +  PLATFORM_GUID                  = 3B9F8782-0799-450C-ACB3-2D8F4504810F
> +  PLATFORM_VERSION               = 0.1
> +  FLASH_DEFINITION               = QuarkPlatformPkg/QuarkCapsule.fdf
> +  OUTPUT_DIRECTORY               = Build/Quark
> +  SUPPORTED_ARCHITECTURES        = IA32
> +  BUILD_TARGETS                  = DEBUG|RELEASE
> +  SKUID_IDENTIFIER               = DEFAULT
> +
> +######################################################################################
> #############
> +#
> +# Components Section - list of the modules and components that will be processed by
> compilation
> +#                      tools and the EDK II tools to generate PE32/PE32+/Coff image
> files.
> +#
> +# Note: The EDK II DSC file is not used to specify how compiled binary images get
> placed
> +#       into firmware volume images. This section is just a list of modules to compile
> from
> +#       source into UEFI-compliant binaries.
> +#       It is the FDF file that contains information on combining binary files into
> firmware
> +#       volume images, whose concept is beyond UEFI and is described in PI
> specification.
> +#       Binary modules do not need to be listed in this section, as they should be
> +#       specified in the FDF file. For example: Shell binary, FAT binary (Fat.efi),
> +#       Logo (Logo.bmp), and etc.
> +#       There may also be modules listed in this section that are not required in the
> FDF file,
> +#       When a module listed here is excluded from FDF file, then UEFI-compliant
> binary will be
> +#       generated for it, but the binary will not be put into any firmware volume.
> +#
> +######################################################################################
> #############
> diff --git a/QuarkPlatformPkg/QuarkCapsule.fdf b/QuarkPlatformPkg/QuarkCapsule.fdf
> new file mode 100644
> index 0000000..d9dac51
> --- /dev/null
> +++ b/QuarkPlatformPkg/QuarkCapsule.fdf
> @@ -0,0 +1,82 @@
> +## @file
> +# FDF file of Clanton Peak CRB platform with 32-bit DXE
> +#
> +# This package provides QuarkNcSocId platform specific capsule.
> +# Copyright (c) 2016 Intel Corporation.
> +#
> +# This program and the accompanying materials
> +# are licensed and made available under the terms and conditions of the BSD License
> +# which accompanies this distribution.  The full text of the license may be found at
> +# http://opensource.org/licenses/bsd-license.php
> +#
> +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +#
> +##
> +
> +[FV.BiosUpdateCargo]
> +FvAlignment        = 16
> +ERASE_POLARITY     = 1
> +MEMORY_MAPPED      = TRUE
> +STICKY_WRITE       = TRUE
> +LOCK_CAP           = TRUE
> +LOCK_STATUS        = TRUE
> +WRITE_DISABLED_CAP = TRUE
> +WRITE_ENABLED_CAP  = TRUE
> +WRITE_STATUS       = TRUE
> +WRITE_LOCK_CAP     = TRUE
> +WRITE_LOCK_STATUS  = TRUE
> +READ_DISABLED_CAP  = TRUE
> +READ_ENABLED_CAP   = TRUE
> +READ_STATUS        = TRUE
> +READ_LOCK_CAP      = TRUE
> +READ_LOCK_STATUS   = TRUE
> +
> +FILE RAW = AF9C9EB2-12AD-4D3E-A4D4-96F6C9966215 {
> +    $(OUTPUT_DIRECTORY)/$(TARGET)_$(TOOL_CHAIN_TAG)/FV/QUARK.fd
> +  }
> +
> +FILE RAW = ce57b167-b0e4-41e8-a897-5f4feb781d40 {
> +    $(OUTPUT_DIRECTORY)/$(TARGET)_$(TOOL_CHAIN_TAG)/FV/CAPSULEDISPATCHFV.Fv
> +  }
> +
> +FILE RAW = 812136D3-4D3A-433A-9418-29BB9BF78F6E {
> +    QuarkPlatformPkg/Feature/Capsule/SystemBiosUpdateConfig/SystemBiosUpdateConfig.ini
> +  }
> +
> +[FmpPayload.FmpPayloadBiosPkcs7]
> +IMAGE_HEADER_INIT_VERSION = 0x02
> +IMAGE_TYPE_ID             = 62af20c0-7016-424a-9bf8-9ccc86584090 # System FMP special
> Guid (do not change it)
> +IMAGE_INDEX               = 0x1
> +HARDWARE_INSTANCE         = 0x0
> +MONOTONIC_COUNT           = 0x2
> +CERTIFICATE_GUID          = 4AAFD29D-68DF-49EE-8AA9-347D375665A7 # PKCS7
> +
> +FILE DATA =
> $(WORKSPACE)/$(OUTPUT_DIRECTORY)/$(TARGET)_$(TOOL_CHAIN_TAG)/FV/BIOSUPDATECARGO.Fv
> +
> +[FmpPayload.FmpPayloadBiosRsa2048]
> +IMAGE_HEADER_INIT_VERSION = 0x02
> +IMAGE_TYPE_ID             = 62af20c0-7016-424a-9bf8-9ccc86584090 # System FMP special
> Guid (do not change it)
> +IMAGE_INDEX               = 0x1
> +HARDWARE_INSTANCE         = 0x0
> +MONOTONIC_COUNT           = 0x2
> +CERTIFICATE_GUID          = A7717414-C616-4977-9420-844712A735BF # RSA2048SHA256
> +
> +FILE DATA =
> $(WORKSPACE)/$(OUTPUT_DIRECTORY)/$(TARGET)_$(TOOL_CHAIN_TAG)/FV/BIOSUPDATECARGO.Fv
> +
> +[Capsule.BiosCapsuleFmpPkcs7]
> +CAPSULE_GUID                = 6dcbd5ed-e82d-4c44-bda1-7194199ad92a # FMP special Guid
> (do not change it)
> +CAPSULE_FLAGS               = PersistAcrossReset,InitiateReset
> +CAPSULE_HEADER_SIZE         = 0x20
> +CAPSULE_HEADER_INIT_VERSION = 0x1
> +
> +FMP_PAYLOAD = FmpPayloadBiosPkcs7
> +
> +[Capsule.BiosCapsuleFmpRsa2048]
> +CAPSULE_GUID                = 6dcbd5ed-e82d-4c44-bda1-7194199ad92a # FMP special Guid
> (do not change it)
> +CAPSULE_FLAGS               = PersistAcrossReset,InitiateReset
> +CAPSULE_HEADER_SIZE         = 0x20
> +CAPSULE_HEADER_INIT_VERSION = 0x1
> +
> +FMP_PAYLOAD = FmpPayloadBiosRsa2048
> +
> --
> 2.7.4.windows.1


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

* Re: [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application.
  2016-09-29  1:06   ` Kinney, Michael D
@ 2016-09-29  2:37     ` Yao, Jiewen
  2016-09-29  6:39       ` Ni, Ruiyu
  0 siblings, 1 reply; 83+ messages in thread
From: Yao, Jiewen @ 2016-09-29  2:37 UTC (permalink / raw)
  To: Kinney, Michael D, edk2-devel@lists.01.org
  Cc: Tian, Feng, Zeng, Star, Gao, Liming, Zhang, Chao B

Right. CapsuleOnDisk is not supported in BIOS yet.
I will remove it in CapsuleApp.

CapsuleApp just works as an agent to pass capsule to CapsuleDxeRuntime driver.
So it is checked by CapsuleDxeRuntime, not CapsuleApp.

Thank you
Yao Jiewen

From: Kinney, Michael D
Sent: Thursday, September 29, 2016 9:06 AM
To: Yao, Jiewen <jiewen.yao@intel.com>; edk2-devel@lists.01.org; Kinney, Michael D <michael.d.kinney@intel.com>
Cc: Tian, Feng <feng.tian@intel.com>; Zeng, Star <star.zeng@intel.com>; Gao, Liming <liming.gao@intel.com>; Zhang, Chao B <chao.b.zhang@intel.com>
Subject: RE: [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application.

Jiewen,

Does the capsule on disk feature provided by this app work?

I tried it with the QuarkPlatformPkg capsule and I can get
The app to copy the capsule to an EFI System Partition, but
The logic after that point looks incomplete.

Also, if I clear the Persist and Reset flags on the capsule,
the immediate processing of the capsule does not work.

Is there any FW code that will look for capsules on disk?

If there are incomplete features in CapsuleApp, then I think
we should remove them.

Mike

> -----Original Message-----
> From: Yao, Jiewen
> Sent: Tuesday, September 20, 2016 11:45 PM
> To: edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>
> Cc: Tian, Feng <feng.tian@intel.com<mailto:feng.tian@intel.com>>; Zeng, Star <star.zeng@intel.com<mailto:star.zeng@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: [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application.
>
> This CapsuleApp can help perform capsule update in UEFI shell environment.
> It can also dump capsule information, capsule status variable, ESRT and FMP.
>
> Cc: Feng Tian <feng.tian@intel.com<mailto:feng.tian@intel.com>>
> Cc: Star Zeng <star.zeng@intel.com<mailto:star.zeng@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 Zhang <chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com>>
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Jiewen Yao <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>
> ---
>  MdeModulePkg/Application/CapsuleApp/AppSupport.c        |  480 +++++++++
>  MdeModulePkg/Application/CapsuleApp/CapsuleApp.c        | 1047 ++++++++++++++++++++
>  MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf      |   71 ++
>  MdeModulePkg/Application/CapsuleApp/CapsuleApp.uni      |   22 +
>  MdeModulePkg/Application/CapsuleApp/CapsuleAppExtra.uni |   19 +
>  MdeModulePkg/Application/CapsuleApp/CapsuleDump.c       |  840 ++++++++++++++++
>  6 files changed, 2479 insertions(+)
>
> diff --git a/MdeModulePkg/Application/CapsuleApp/AppSupport.c
> b/MdeModulePkg/Application/CapsuleApp/AppSupport.c
> new file mode 100644
> index 0000000..365067d
> --- /dev/null
> +++ b/MdeModulePkg/Application/CapsuleApp/AppSupport.c
> @@ -0,0 +1,480 @@
> +/** @file
> +  A shell application that triggers capsule update process.
> +
> +  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the BSD License
> +  which accompanies this distribution.  The full text of the license may be found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +
> +**/
> +
> +#include <Uefi.h>
> +#include <Library/BaseLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/UefiRuntimeServicesTableLib.h>
> +#include <Library/UefiLib.h>
> +#include <Library/PrintLib.h>
> +#include <Protocol/LoadedImage.h>
> +#include <Protocol/SimpleFileSystem.h>
> +#include <Guid/FileInfo.h>
> +#include <Guid/Gpt.h>
> +
> +#define MAX_ARG_NUM     11
> +
> +UINTN  Argc = 0;
> +CHAR16 *Argv[MAX_ARG_NUM];
> +CHAR16 *ArgBuffer;
> +
> +/**
> +
> +  This function parse application ARG.
> +
> +  @return Status
> +**/
> +EFI_STATUS
> +GetArg (
> +  VOID
> +  )
> +{
> +  UINT8                         *Data;
> +  UINTN                         DataSize;
> +  CHAR16                        *Index;
> +  CHAR16                        *End;
> +  CHAR16                        *DIndex;
> +  EFI_STATUS                    Status;
> +  EFI_LOADED_IMAGE_PROTOCOL     *LoadedImage;
> +
> +  Status = gBS->HandleProtocol (
> +                  gImageHandle,
> +                  &gEfiLoadedImageProtocolGuid,
> +                  (VOID**)&LoadedImage
> +                  );
> +  if (EFI_ERROR(Status)) {
> +    return Status;
> +  }
> +
> +  Data = LoadedImage->LoadOptions;
> +  DataSize = LoadedImage->LoadOptionsSize;
> +
> +  End = (CHAR16*)(UINTN)(Data + DataSize);
> +  Status = gBS->AllocatePool (EfiBootServicesData, DataSize, (VOID **)&ArgBuffer);
> +  ASSERT_EFI_ERROR (Status);
> +  DIndex = ArgBuffer;
> +  Argv[Argc++] = ArgBuffer;
> +  for (Index = (CHAR16*)Data; Index < End; ) {
> +    if (*Index == L' ') {
> +      *DIndex = L'\0';
> +      if (Argc >= MAX_ARG_NUM) {
> +        return EFI_UNSUPPORTED;
> +      }
> +      Argv[Argc++] = (++ DIndex);
> +      while(*Index == L' ') {
> +        Index ++;
> +      }
> +    }
> +    (*(DIndex ++)) = (*(Index ++));
> +  }
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Clear APP ARG.
> +**/
> +VOID
> +CleanArg (
> +  VOID
> +  )
> +{
> +  FreePool (Argv[0]);
> +}
> +
> +/**
> +  Return File System Volume containing this shell application.
> +
> +  @return File System Volume containing this shell application.
> +**/
> +EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *
> +GetMyVol (
> +  VOID
> +  )
> +{
> +  EFI_STATUS                        Status;
> +  EFI_LOADED_IMAGE_PROTOCOL         *LoadedImage;
> +  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Vol;
> +
> +  Status = gBS->HandleProtocol (
> +                  gImageHandle,
> +                  &gEfiLoadedImageProtocolGuid,
> +                  (VOID **)&LoadedImage
> +                  );
> +  ASSERT_EFI_ERROR (Status);
> +
> +  Status = gBS->HandleProtocol (
> +                  LoadedImage->DeviceHandle,
> +                  &gEfiSimpleFileSystemProtocolGuid,
> +                  (VOID **)&Vol
> +                  );
> +  if (!EFI_ERROR (Status)) {
> +    return Vol;
> +  }
> +
> +  return NULL;
> +}
> +
> +/**
> +  Read a file from this volume.
> +
> +  @param Vol             File System Volume
> +  @param FileName        The file to be read.
> +  @param BufferSize      The file buffer size
> +  @param Buffer          The file buffer
> +
> +  @retval EFI_SUCCESS    Read file successfully
> +  @retval EFI_NOT_FOUND  File not found
> +**/
> +EFI_STATUS
> +ReadFileFromVol (
> +  IN  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Vol,
> +  IN  CHAR16                            *FileName,
> +  OUT UINTN                             *BufferSize,
> +  OUT VOID                              **Buffer
> +  )
> +{
> +  EFI_STATUS                        Status;
> +  EFI_FILE_HANDLE                   RootDir;
> +  EFI_FILE_HANDLE                   Handle;
> +  UINTN                             FileInfoSize;
> +  EFI_FILE_INFO                     *FileInfo;
> +  UINTN                             TempBufferSize;
> +  VOID                              *TempBuffer;
> +
> +  //
> +  // Open the root directory
> +  //
> +  Status = Vol->OpenVolume (Vol, &RootDir);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  //
> +  // Open the file
> +  //
> +  Status = RootDir->Open (
> +                      RootDir,
> +                      &Handle,
> +                      FileName,
> +                      EFI_FILE_MODE_READ,
> +                      0
> +                      );
> +  if (EFI_ERROR (Status)) {
> +    RootDir->Close (RootDir);
> +    return Status;
> +  }
> +
> +  RootDir->Close (RootDir);
> +
> +  //
> +  // Get the file information
> +  //
> +  FileInfoSize = sizeof(EFI_FILE_INFO) + 1024;
> +
> +  FileInfo = AllocateZeroPool (FileInfoSize);
> +  if (FileInfo == NULL) {
> +    Handle->Close (Handle);
> +    return Status;
> +  }
> +
> +  Status = Handle->GetInfo (
> +                     Handle,
> +                     &gEfiFileInfoGuid,
> +                     &FileInfoSize,
> +                     FileInfo
> +                     );
> +  if (EFI_ERROR (Status)) {
> +    Handle->Close (Handle);
> +    gBS->FreePool (FileInfo);
> +    return Status;
> +  }
> +
> +  //
> +  // Allocate buffer for the file data. The last CHAR16 is for L'\0'
> +  //
> +  TempBufferSize = (UINTN) FileInfo->FileSize + sizeof(CHAR16);
> +  TempBuffer = AllocateZeroPool (TempBufferSize);
> +  if (TempBuffer == NULL) {
> +    Handle->Close (Handle);
> +    gBS->FreePool (FileInfo);
> +    return Status;
> +  }
> +
> +  gBS->FreePool (FileInfo);
> +
> +  //
> +  // Read the file data to the buffer
> +  //
> +  Status = Handle->Read (
> +                     Handle,
> +                     &TempBufferSize,
> +                     TempBuffer
> +                     );
> +  if (EFI_ERROR (Status)) {
> +    Handle->Close (Handle);
> +    gBS->FreePool (TempBuffer);
> +    return Status;
> +  }
> +
> +  Handle->Close (Handle);
> +
> +  *BufferSize = TempBufferSize;
> +  *Buffer     = TempBuffer;
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Read a file.
> +  If ScanFs is FLASE, it will use this Vol as default Fs.
> +  If ScanFs is TRUE, it will scan all FS and check the file.
> +    If there is only one file match the name, it will be read.
> +    If there is more than one file match the name, it will return Error.
> +
> +  @param ThisVol         File System Volume
> +  @param FileName        The file to be read.
> +  @param BufferSize      The file buffer size
> +  @param Buffer          The file buffer
> +  @param ScanFs          Need Scan all FS
> +
> +  @retval EFI_SUCCESS    Read file successfully
> +  @retval EFI_NOT_FOUND  File not found
> +  @retval EFI_NO_MAPPING There is duplicated files found
> +**/
> +EFI_STATUS
> +ReadFileToBufferEx (
> +  IN OUT EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   **ThisVol,
> +  IN  CHAR16                               *FileName,
> +  OUT UINTN                                *BufferSize,
> +  OUT VOID                                 **Buffer,
> +  IN  BOOLEAN                              ScanFs
> +  )
> +{
> +  EFI_STATUS                        Status;
> +  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Vol;
> +  UINTN                             TempBufferSize;
> +  VOID                              *TempBuffer;
> +  UINTN                             NoHandles;
> +  EFI_HANDLE                        *HandleBuffer;
> +  UINTN                             Index;
> +
> +  //
> +  // Check parameters
> +  //
> +  if ((FileName == NULL) || (Buffer == NULL) || (ThisVol == NULL)) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  //
> +  // not scan fs
> +  //
> +  if (!ScanFs) {
> +    if (*ThisVol == NULL) {
> +      *ThisVol = GetMyVol ();
> +      if (*ThisVol == NULL) {
> +        return EFI_INVALID_PARAMETER;
> +      }
> +    }
> +    //
> +    // Read file directly from Vol
> +    //
> +    return ReadFileFromVol (*ThisVol, FileName, BufferSize, Buffer);
> +  }
> +
> +  //
> +  // need scan fs
> +  //
> +
> +  //
> +  // Get all Vol handle
> +  //
> +  Status = gBS->LocateHandleBuffer (
> +                   ByProtocol,
> +                   &gEfiSimpleFileSystemProtocolGuid,
> +                   NULL,
> +                   &NoHandles,
> +                   &HandleBuffer
> +                   );
> +  if (EFI_ERROR (Status) && (NoHandles == 0)) {
> +    return EFI_NOT_FOUND;
> +  }
> +
> +  //
> +  // Walk through each Vol
> +  //
> +  *ThisVol = NULL;
> +  *BufferSize = 0;
> +  *Buffer     = NULL;
> +  for (Index = 0; Index < NoHandles; Index++) {
> +    Status = gBS->HandleProtocol (
> +                    HandleBuffer[Index],
> +                    &gEfiSimpleFileSystemProtocolGuid,
> +                    (VOID **)&Vol
> +                    );
> +    if (EFI_ERROR(Status)) {
> +      continue;
> +    }
> +
> +    Status = ReadFileFromVol (Vol, FileName, &TempBufferSize, &TempBuffer);
> +    if (!EFI_ERROR (Status)) {
> +      //
> +      // Read file OK, check duplication
> +      //
> +      if (*ThisVol != NULL) {
> +        //
> +        // Find the duplicated file
> +        //
> +        gBS->FreePool (TempBuffer);
> +        gBS->FreePool (*Buffer);
> +        Print (L"Duplicated FileName found!\n");
> +        return EFI_NO_MAPPING;
> +      } else {
> +        //
> +        // Record value
> +        //
> +        *ThisVol = Vol;
> +        *BufferSize = TempBufferSize;
> +        *Buffer     = TempBuffer;
> +      }
> +    }
> +  }
> +
> +  //
> +  // Scan Fs done
> +  //
> +  if (*ThisVol == NULL) {
> +    return EFI_NOT_FOUND;
> +  }
> +
> +  //
> +  // Done
> +  //
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Read a file.
> +
> +  @param FileName        The file to be read.
> +  @param BufferSize      The file buffer size
> +  @param Buffer          The file buffer
> +
> +  @retval EFI_SUCCESS    Read file successfully
> +  @retval EFI_NOT_FOUND  File not found
> +**/
> +EFI_STATUS
> +ReadFileToBuffer (
> +  IN  CHAR16                               *FileName,
> +  OUT UINTN                                *BufferSize,
> +  OUT VOID                                 **Buffer
> +  )
> +{
> +  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Vol;
> +  Vol = NULL;
> +  return ReadFileToBufferEx(&Vol, FileName, BufferSize, Buffer, FALSE);
> +}
> +
> +/**
> +  Write a file.
> +
> +  @param FileName        The file to be written.
> +  @param BufferSize      The file buffer size
> +  @param Buffer          The file buffer
> +
> +  @retval EFI_SUCCESS    Write file successfully
> +**/
> +EFI_STATUS
> +WriteFileFromBuffer(
> +  IN  CHAR16                               *FileName,
> +  IN  UINTN                                BufferSize,
> +  IN  VOID                                 *Buffer
> +  )
> +{
> +  EFI_STATUS                        Status;
> +  EFI_FILE_HANDLE                   RootDir;
> +  EFI_FILE_HANDLE                   Handle;
> +  UINTN                             TempBufferSize;
> +  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Vol;
> +
> +  Vol = GetMyVol();
> +
> +  //
> +  // Open the root directory
> +  //
> +  Status = Vol->OpenVolume (Vol, &RootDir);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  //
> +  // Open the file
> +  //
> +  Status = RootDir->Open (
> +                      RootDir,
> +                      &Handle,
> +                      FileName,
> +                      EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE| EFI_FILE_MODE_CREATE,
> +                      0
> +                      );
> +  if (EFI_ERROR (Status)) {
> +    RootDir->Close (RootDir);
> +    return Status;
> +  }
> +
> +  //
> +  // Delete file
> +  //
> +  Status = Handle->Delete(Handle);
> +  if (EFI_ERROR(Status)) {
> +    return Status;
> +  }
> +
> +  //
> +  // Open the file again
> +  //
> +  Status = RootDir->Open (
> +                      RootDir,
> +                      &Handle,
> +                      FileName,
> +                      EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE| EFI_FILE_MODE_CREATE,
> +                      0
> +                      );
> +  if (EFI_ERROR (Status)) {
> +    RootDir->Close (RootDir);
> +    return Status;
> +  }
> +
> +  RootDir->Close (RootDir);
> +
> +  //
> +  // Write the file data from the buffer
> +  //
> +  TempBufferSize = BufferSize;
> +  Status = Handle->Write (
> +                     Handle,
> +                     &TempBufferSize,
> +                     Buffer
> +                     );
> +  if (EFI_ERROR (Status)) {
> +    Handle->Close (Handle);
> +    return Status;
> +  }
> +
> +  Handle->Close (Handle);
> +
> +  return EFI_SUCCESS;
> +}
> +
> diff --git a/MdeModulePkg/Application/CapsuleApp/CapsuleApp.c
> b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.c
> new file mode 100644
> index 0000000..0a28557
> --- /dev/null
> +++ b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.c
> @@ -0,0 +1,1047 @@
> +/** @file
> +  A shell application that triggers capsule update process.
> +
> +  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the BSD License
> +  which accompanies this distribution.  The full text of the license may be found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +
> +**/
> +
> +#include <Uefi.h>
> +#include <Library/BaseLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/UefiRuntimeServicesTableLib.h>
> +#include <Library/UefiLib.h>
> +#include <Library/PrintLib.h>
> +#include <Protocol/LoadedImage.h>
> +#include <Protocol/SimpleFileSystem.h>
> +#include <Protocol/GraphicsOutput.h>
> +#include <Guid/FileInfo.h>
> +#include <Guid/Gpt.h>
> +#include <Guid/GlobalVariable.h>
> +#include <Guid/CapsuleReport.h>
> +#include <Guid/SystemResourceTable.h>
> +#include <Guid/FmpCapsule.h>
> +#include <IndustryStandard/WindowsUxCapsule.h>
> +
> +#define CAPSULE_HEADER_SIZE  0x20
> +
> +#define NESTED_CAPSULE_HEADER_SIZE  SIZE_4KB
> +#define SYSTEM_FIRMWARE_FLAG 0x50000
> +#define DEVICE_FIRMWARE_FLAG 0x78010
> +
> +#define EFI_CAPSULE_FROM_FILE_DIR                           L"\\EFI\\UpdateCapsule\\<file:///\\EFI\UpdateCapsule\>"
> +#define EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED  0x0000000000000004
> +
> +#define MAJOR_VERSION   1
> +#define MINOR_VERSION   0
> +
> +#define MAX_ARG_NUM     11
> +#define MAX_CAPSULE_NUM (MAX_ARG_NUM - 1)
> +
> +extern UINTN  Argc;
> +extern CHAR16 *Argv[];
> +
> +//
> +// Define how many block descriptors we want to test with.
> +//
> +UINTN  NumberOfDescriptors = 1;
> +UINTN  CapsuleFirstIndex;
> +UINTN  CapsuleLastIndex;
> +
> +/**
> +  Dump capsule information
> +
> +  @retval EFI_SUCCESS            The capsule information is dumped.
> +  @retval EFI_UNSUPPORTED        Input parameter is not valid.
> +**/
> +EFI_STATUS
> +DumpCapsule(
> +  VOID
> +  );
> +
> +/**
> +  Dump capsule status variable.
> +
> +  @retval EFI_SUCCESS            The capsule status variable is dumped.
> +  @retval EFI_UNSUPPORTED        Input parameter is not valid.
> +**/
> +EFI_STATUS
> +DmpCapsuleStatusVariable(
> +  VOID
> +  );
> +
> +/**
> +  Dump FMP protocol info.
> +**/
> +VOID
> +DumpFmpData(
> +  VOID
> +  );
> +
> +/**
> +  Dump ESRT info.
> +**/
> +VOID
> +DumpEsrtData(
> +  VOID
> +  );
> +
> +/**
> +  Read a file.
> +
> +  @param FileName        The file to be read.
> +  @param BufferSize      The file buffer size
> +  @param Buffer          The file buffer
> +
> +  @retval EFI_SUCCESS    Read file successfully
> +  @retval EFI_NOT_FOUND  File not found
> +**/
> +EFI_STATUS
> +ReadFileToBuffer(
> +  IN  CHAR16                               *FileName,
> +  OUT UINTN                                *BufferSize,
> +  OUT VOID                                 **Buffer
> +  );
> +
> +/**
> +  Write a file.
> +
> +  @param FileName        The file to be written.
> +  @param BufferSize      The file buffer size
> +  @param Buffer          The file buffer
> +
> +  @retval EFI_SUCCESS    Write file successfully
> +**/
> +EFI_STATUS
> +WriteFileFromBuffer(
> +  IN  CHAR16                               *FileName,
> +  IN  UINTN                                BufferSize,
> +  IN  VOID                                 *Buffer
> +  );
> +
> +/**
> +
> +  This function parse application ARG.
> +
> +  @return Status
> +**/
> +EFI_STATUS
> +GetArg (
> +  VOID
> +  );
> +
> +/**
> +  Clear APP ARG.
> +**/
> +VOID
> +CleanArg (
> +  VOID
> +  );
> +
> +/**
> +  Create UX capsule.
> +
> +  @retval EFI_SUCCESS            The capsule header is appended.
> +  @retval EFI_UNSUPPORTED        Input parameter is not valid.
> +  @retval EFI_OUT_OF_RESOURCES   No enough resource to create UX capsule.
> +**/
> +EFI_STATUS
> +CreateBmpFmp(
> +  VOID
> +  )
> +{
> +  CHAR16                                        *OutputCapsuleName;
> +  VOID                                          *BmpBuffer;
> +  UINTN                                         FileSize;
> +  CHAR16                                        *BmpName;
> +  UINT8                                         *FullCapsuleBuffer;
> +  UINTN                                         FullCapsuleBufferSize;
> +  EFI_DISPLAY_CAPSULE                           *DisplayCapsule;
> +  EFI_STATUS                                    Status;
> +  EFI_GRAPHICS_OUTPUT_PROTOCOL                  *Gop;
> +
> +  Status = gBS->LocateProtocol(&gEfiGraphicsOutputProtocolGuid, NULL, (VOID **)&Gop);
> +  if (EFI_ERROR(Status)) {
> +    Print(L"CapsuleApp: NO GOP is found.\n");
> +    return EFI_UNSUPPORTED;
> +  }
> +  Print(L"Current GOP: Mode - %d, ", Gop->Mode->Mode);
> +  Print(L"HorizontalResolution - %d, ", Gop->Mode->Info->HorizontalResolution);
> +  Print(L"VerticalResolution - %d\n", Gop->Mode->Info->VerticalResolution);
> +  // HorizontalResolution >= BMP_IMAGE_HEADER.PixelWidth
> +  // VerticalResolution   >= BMP_IMAGE_HEADER.PixelHeight
> +
> +  if (Argc != 5) {
> +    Print(L"CapsuleApp: Invalid Parameter.\n");
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  if (StrCmp(Argv[3], L"-O") != 0) {
> +    Print(L"CapsuleApp: NO output capsule name.\n");
> +    return EFI_UNSUPPORTED;
> +  }
> +  OutputCapsuleName = Argv[4];
> +
> +  BmpBuffer = NULL;
> +  FileSize = 0;
> +  FullCapsuleBuffer = NULL;
> +
> +  BmpName = Argv[2];
> +  Status = ReadFileToBuffer(BmpName, &FileSize, &BmpBuffer);
> +  if (EFI_ERROR(Status)) {
> +    Print(L"CapsuleApp: BMP image (%s) is not found.\n", BmpName);
> +    goto Done;
> +  }
> +
> +  FullCapsuleBufferSize = sizeof(EFI_DISPLAY_CAPSULE) + FileSize;
> +  FullCapsuleBuffer = AllocatePool(FullCapsuleBufferSize);
> +  if (FullCapsuleBuffer == NULL) {
> +    Print(L"CapsuleApp: Capsule Buffer size (0x%x) too big.\n",
> FullCapsuleBufferSize);
> +    Status = EFI_OUT_OF_RESOURCES;
> +    goto Done;
> +  }
> +
> +  DisplayCapsule = (EFI_DISPLAY_CAPSULE *)FullCapsuleBuffer;
> +  CopyGuid(&DisplayCapsule->CapsuleHeader.CapsuleGuid, &gWindowsUxCapsuleGuid);
> +  DisplayCapsule->CapsuleHeader.HeaderSize = sizeof(DisplayCapsule->CapsuleHeader);
> +  DisplayCapsule->CapsuleHeader.Flags = CAPSULE_FLAGS_PERSIST_ACROSS_RESET;
> +  DisplayCapsule->CapsuleHeader.CapsuleImageSize = (UINT32)FullCapsuleBufferSize;
> +
> +  DisplayCapsule->ImagePayload.Version = 1;
> +  DisplayCapsule->ImagePayload.Checksum = 0;
> +  DisplayCapsule->ImagePayload.ImageType = 0; // BMP
> +  DisplayCapsule->ImagePayload.Reserved = 0;
> +  DisplayCapsule->ImagePayload.Mode = Gop->Mode->Mode;
> +  DisplayCapsule->ImagePayload.OffsetX = 0;
> +  DisplayCapsule->ImagePayload.OffsetY = 0;
> +
> +  CopyMem((DisplayCapsule + 1), BmpBuffer, FileSize);
> +
> +  DisplayCapsule->ImagePayload.Checksum = CalculateCheckSum8(FullCapsuleBuffer,
> FullCapsuleBufferSize);
> +
> +  Status = WriteFileFromBuffer(OutputCapsuleName, FullCapsuleBufferSize,
> FullCapsuleBuffer);
> +  Print(L"CapsuleApp: Write %s %r\n", OutputCapsuleName, Status);
> +
> +Done:
> +  if (BmpBuffer != NULL) {
> +    FreePool(BmpBuffer);
> +  }
> +
> +  if (FullCapsuleBuffer != NULL) {
> +    FreePool(FullCapsuleBuffer);
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  Get ImageTypeId in the FMP capsule header.
> +
> +  @param CapsuleHeader  The FMP capsule image header.
> +
> +  @return ImageTypeId
> +**/
> +EFI_GUID *
> +GetCapsuleImageTypeId(
> +  IN EFI_CAPSULE_HEADER                            *CapsuleHeader
> +  )
> +{
> +  EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER       *FmpCapsuleHeader;
> +  UINT64                                       *ItemOffsetList;
> +  EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader;
> +
> +  FmpCapsuleHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *)((UINT8 *)CapsuleHeader
> + CapsuleHeader->HeaderSize);
> +  ItemOffsetList = (UINT64 *)(FmpCapsuleHeader + 1);
> +  if (FmpCapsuleHeader->PayloadItemCount == 0) {
> +    return NULL;
> +  }
> +  ImageHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *)((UINT8
> *)FmpCapsuleHeader + ItemOffsetList[FmpCapsuleHeader->EmbeddedDriverCount]);
> +  return &ImageHeader->UpdateImageTypeId;
> +}
> +
> +/**
> +  Get ESRT FwType according to ImageTypeId
> +
> +  @param  ImageTypeId   ImageTypeId of an FMP capsule.
> +
> +  @return ESRT FwType
> +**/
> +UINT32
> +GetEsrtFwType(
> +  IN  EFI_GUID                                      *ImageTypeId
> +  )
> +{
> +  EFI_STATUS                 Status;
> +  EFI_SYSTEM_RESOURCE_TABLE  *Esrt;
> +  EFI_SYSTEM_RESOURCE_ENTRY  *EsrtEntry;
> +  UINTN                      Index;
> +
> +  //
> +  // Check ESRT
> +  //
> +  Status = EfiGetSystemConfigurationTable(&gEfiSystemResourceTableGuid, (VOID
> **)&Esrt);
> +  if (!EFI_ERROR(Status)) {
> +    EsrtEntry = (VOID *)(Esrt + 1);
> +    for (Index = 0; Index < Esrt->FwResourceCount; Index++, EsrtEntry++) {
> +      if (CompareGuid(&EsrtEntry->FwClass, ImageTypeId)) {
> +        return EsrtEntry->FwType;
> +      }
> +    }
> +  }
> +
> +  return ESRT_FW_TYPE_UNKNOWN;
> +}
> +
> +/**
> +  Append a capsule header on top of current image.
> +  This function follows Windows UEFI Firmware Update Platform document.
> +
> +  @retval EFI_SUCCESS            The capsule header is appended.
> +  @retval EFI_UNSUPPORTED        Input parameter is not valid.
> +  @retval EFI_OUT_OF_RESOURCES   No enough resource to append capsule header.
> +**/
> +EFI_STATUS
> +CreateNestedFmp(
> +  VOID
> +  )
> +{
> +  CHAR16                                        *OutputCapsuleName;
> +  VOID                                          *CapsuleBuffer;
> +  UINTN                                         FileSize;
> +  CHAR16                                        *CapsuleName;
> +  UINT8                                         *FullCapsuleBuffer;
> +  UINTN                                         FullCapsuleBufferSize;
> +  EFI_CAPSULE_HEADER                            *NestedCapsuleHeader;
> +  EFI_GUID                                      *ImageTypeId;
> +  UINT32                                        FwType;
> +  EFI_STATUS                                    Status;
> +
> +  if (Argc != 5) {
> +    Print(L"CapsuleApp: Invalid Parameter.\n");
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  if (StrCmp(Argv[3], L"-O") != 0) {
> +    Print(L"CapsuleApp: NO output capsule name.\n");
> +    return EFI_UNSUPPORTED;
> +  }
> +  OutputCapsuleName = Argv[4];
> +
> +  CapsuleBuffer = NULL;
> +  FileSize = 0;
> +  FullCapsuleBuffer = NULL;
> +
> +  CapsuleName = Argv[2];
> +  Status = ReadFileToBuffer(CapsuleName, &FileSize, &CapsuleBuffer);
> +  if (EFI_ERROR(Status)) {
> +    Print(L"CapsuleApp: Capsule image (%s) is not found.\n", CapsuleName);
> +    goto Done;
> +  }
> +
> +  ImageTypeId = GetCapsuleImageTypeId(CapsuleBuffer);
> +  if (ImageTypeId == NULL) {
> +    Print(L"CapsuleApp: Capsule ImageTypeId is not found.\n");
> +    goto Done;
> +  }
> +  FwType = GetEsrtFwType(ImageTypeId);
> +  if ((FwType != ESRT_FW_TYPE_SYSTEMFIRMWARE) && (FwType !=
> ESRT_FW_TYPE_DEVICEFIRMWARE)) {
> +    Print(L"CapsuleApp: Capsule FwType is invalid.\n");
> +    goto Done;
> +  }
> +
> +  FullCapsuleBufferSize = NESTED_CAPSULE_HEADER_SIZE + FileSize;
> +  FullCapsuleBuffer = AllocatePool(FullCapsuleBufferSize);
> +  if (FullCapsuleBuffer == NULL) {
> +    Print(L"CapsuleApp: Capsule Buffer size (0x%x) too big.\n",
> FullCapsuleBufferSize);
> +    Status = EFI_OUT_OF_RESOURCES;
> +    goto Done;
> +  }
> +
> +  NestedCapsuleHeader = (EFI_CAPSULE_HEADER *)FullCapsuleBuffer;
> +  ZeroMem(NestedCapsuleHeader, NESTED_CAPSULE_HEADER_SIZE);
> +  CopyGuid(&NestedCapsuleHeader->CapsuleGuid, ImageTypeId);
> +  NestedCapsuleHeader->HeaderSize = NESTED_CAPSULE_HEADER_SIZE;
> +  NestedCapsuleHeader->Flags = (FwType == ESRT_FW_TYPE_DEVICEFIRMWARE) ?
> SYSTEM_FIRMWARE_FLAG : DEVICE_FIRMWARE_FLAG;
> +  NestedCapsuleHeader->CapsuleImageSize = (UINT32)FullCapsuleBufferSize;
> +
> +  CopyMem((UINT8 *)NestedCapsuleHeader + NestedCapsuleHeader->HeaderSize,
> CapsuleBuffer, FileSize);
> +
> +  Status = WriteFileFromBuffer(OutputCapsuleName, FullCapsuleBufferSize,
> FullCapsuleBuffer);
> +  Print(L"CapsuleApp: Write %s %r\n", OutputCapsuleName, Status);
> +
> +Done:
> +  if (CapsuleBuffer != NULL) {
> +    FreePool(CapsuleBuffer);
> +  }
> +
> +  if (FullCapsuleBuffer != NULL) {
> +    FreePool(FullCapsuleBuffer);
> +  }
> +
> +  return Status;
> +}
> +
> +
> +/**
> +  Clear capsule status variable.
> +
> +  @retval EFI_SUCCESS            The capsule status variable is cleared.
> +**/
> +EFI_STATUS
> +ClearCapsuleStatusVariable(
> +  VOID
> +  )
> +{
> +  EFI_STATUS                          Status;
> +  UINT32                              Index;
> +  CHAR16                              CapsuleVarName[20];
> +  CHAR16                              *TempVarName;
> +
> +  StrCpyS (CapsuleVarName, sizeof(CapsuleVarName)/sizeof(CapsuleVarName[0]),
> L"Capsule");
> +  TempVarName = CapsuleVarName + StrLen (CapsuleVarName);
> +  Index = 0;
> +
> +  while (TRUE) {
> +    UnicodeSPrint (TempVarName, 5 * sizeof(CHAR16), L"%04x", Index);
> +
> +    Status = gRT->SetVariable (
> +                    CapsuleVarName,
> +                    &gEfiCapsuleReportGuid,
> +                    EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS |
> EFI_VARIABLE_BOOTSERVICE_ACCESS,
> +                    0,
> +                    (VOID *)NULL
> +                    );
> +    if (EFI_ERROR(Status)) {
> +      //
> +      // There is no capsule variables, quit
> +      //
> +      break;
> +    }
> +
> +    Index++;
> +    if (Index > 0xFFFF) {
> +      break;
> +    }
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Get the active UEFI system partition from bootoption list.
> +
> +  @param[out] Fs    Simple File System protocol on the active UEFI system partition
> +
> +  @retval EFI_SUCCESS   active UEFI system partition found
> +**/
> +EFI_STATUS
> +GetEfiSysPartition(
> +  OUT EFI_SIMPLE_FILE_SYSTEM_PROTOCOL **Fs
> +  )
> +{
> +  EFI_STATUS                       Status;
> +  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL  *FsTemp;
> +  UINTN                            NoHandles;
> +  EFI_HANDLE                       *Handles;
> +  UINTN                            Index;
> +
> +  Handles = NULL;
> +
> +  //
> +  // search for EFI system partition protocol on Boot option device path
> +  //
> +  Status = gBS->LocateHandleBuffer(ByProtocol, &gEfiPartTypeSystemPartGuid, NULL,
> &NoHandles, &Handles);
> +  if (EFI_ERROR(Status)) {
> +    return Status;
> +  }
> +
> +  //
> +  // Skip BootOptions within FV
> +  //
> +  for (Index = 0; Index < NoHandles; Index++) {
> +    Status = gBS->HandleProtocol (Handles[Index], &gEfiSimpleFileSystemProtocolGuid,
> (VOID **)&FsTemp);
> +    if (!EFI_ERROR (Status)){
> +      *Fs = FsTemp;
> +      break;
> +    }
> +  }
> +  return Status;
> +}
> +
> +/**
> +  Copy a list of capsule images to the active UEFI system partition from bootoption
> list.
> +
> +  @param[in] CapsuleBuffer    An array of pointer to capsule images
> +  @param[in] FileSize         An array of UINTN to capsule images size
> +  @param[in] CapsuleNum       The count of capsule images
> +
> +  @retval EFI_SUCCESS   Capsule images are copied to the active UEFI system partition
> +**/
> +EFI_STATUS
> +CopyCapsuleToActiveEfiPartition(
> +  IN VOID                          **CapsuleBuffer,
> +  IN UINTN                         *FileSize,
> +  IN UINTN                         CapsuleNum
> +  )
> +{
> +  EFI_STATUS                       Status;
> +  CHAR16                           *CapsuleName;
> +  UINTN                            Index;
> +  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL  *Fs;
> +  EFI_FILE_HANDLE                  RootDir;
> +  EFI_FILE_HANDLE                  CapsuleDir;
> +  EFI_FILE_HANDLE                  DestHandle;
> +  UINTN                            DataSize;
> +  UINT64                           OsIndication;
> +
> +  RootDir      = NULL;
> +  CapsuleDir   = NULL;
> +
> +  Status = GetEfiSysPartition(&Fs);
> +  if (EFI_ERROR(Status)) {
> +    Print (L"Can not find active UEFI System Partition\n");
> +    return Status;
> +  }
> +
> +  Status = Fs->OpenVolume(Fs, &RootDir);
> +  if (EFI_ERROR(Status)) {
> +    goto EXIT;
> +  }
> +
> +  Status = RootDir->Open(
> +                      RootDir,
> +                      &CapsuleDir,
> +                      EFI_CAPSULE_FROM_FILE_DIR,
> +                      EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE,
> +                      EFI_FILE_DIRECTORY
> +                      );
> +  if (EFI_ERROR(Status)) {
> +    goto EXIT;
> +  }
> +
> +  //
> +  // Read the input files.
> +  //
> +  for (Index = 0; Index < CapsuleNum; Index++) {
> +    CapsuleName = Argv[CapsuleFirstIndex + Index];
> +    Status = CapsuleDir->Open(
> +                           CapsuleDir,
> +                           &DestHandle,
> +                           CapsuleName,
> +                           EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE |
> EFI_FILE_MODE_CREATE,
> +                           EFI_FILE_ARCHIVE
> +                           );
> +    if (EFI_ERROR(Status)) {
> +      Print(L"CapsuleApp: %s open error - %r\n", CapsuleName, Status);
> +      continue;
> +    }
> +
> +    DataSize = FileSize[Index];
> +    Status = DestHandle->Write(
> +                           DestHandle,
> +                           &DataSize,
> +                           CapsuleBuffer[Index]
> +                           );
> +    DestHandle->Close(DestHandle);
> +    if (EFI_ERROR(Status)) {
> +      Print(L"CapsuleApp: %s write error - %r, FileSize - 0x%x\n", CapsuleName,
> Status, FileSize[Index]);
> +    }
> +  }
> +
> +  Status = gRT->GetVariable (
> +                  L"OsIndications",
> +                  &gEfiGlobalVariableGuid,
> +                  NULL,
> +                  &DataSize,
> +                  (VOID *) &OsIndication
> +                  );
> +
> +  if (EFI_ERROR(Status) || DataSize != sizeof(OsIndication)) {
> +    OsIndication = 0;
> +  }
> +
> +  //
> +  // Set OsIndications Variable EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED bit
> +  //
> +  OsIndication |= EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED;
> +  Status = gRT->SetVariable (
> +                  L"OsIndications",
> +                  &gEfiGlobalVariableGuid,
> +                  EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS |
> +                  EFI_VARIABLE_BOOTSERVICE_ACCESS,
> +                  sizeof(OsIndication),
> +                  (VOID *)&OsIndication
> +                  );
> +
> +
> +EXIT:
> +  if (RootDir != NULL) {
> +    RootDir->Close(RootDir);
> +  }
> +
> +  if (CapsuleDir != NULL) {
> +    CapsuleDir->Close(CapsuleDir);
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  Build Gather list for a list of capsule images.
> +
> +  @param[in]  CapsuleBuffer    An array of pointer to capsule images
> +  @param[in]  FileSize         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                         *FileSize,
> +  IN UINTN                         CapsuleNum,
> +  OUT EFI_CAPSULE_BLOCK_DESCRIPTOR **BlockDescriptors
> +  )
> +{
> +  EFI_STATUS                    Status;
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR  *BlockDescriptors1;
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR  *BlockDescriptors2;
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR  *BlockDescriptorPre;
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR  *BlockDescriptorsHeader;
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR  *TempBlockPtr;
> +  UINT8                         *TempDataPtr;
> +  UINTN                         SizeLeft;
> +  UINTN                         Size;
> +  INT32                         Count;
> +  INT32                         Number;
> +  UINTN                         Index;
> +
> +  TempBlockPtr           = NULL;
> +  BlockDescriptors1      = NULL;
> +  BlockDescriptors2      = NULL;
> +  BlockDescriptorPre     = NULL;
> +  BlockDescriptorsHeader = NULL;
> +
> +  for (Index = 0; Index < CapsuleNum; Index++) {
> +    //
> +    // Allocate memory for the descriptors.
> +    //
> +    if (NumberOfDescriptors == 1) {
> +      Count = 2;
> +    } else {
> +      Count = (INT32)(NumberOfDescriptors + 2) / 2;
> +    }
> +
> +    Size               = Count * sizeof (EFI_CAPSULE_BLOCK_DESCRIPTOR);
> +    BlockDescriptors1  = AllocateRuntimeZeroPool (Size);
> +    if (BlockDescriptors1 == NULL) {
> +      Print (L"CapsuleApp: failed to allocate memory for descriptors\n");
> +      Status = EFI_OUT_OF_RESOURCES;
> +      goto ERREXIT;
> +    } else {
> +      Print (L"CapsuleApp: creating capsule descriptors at 0x%X\n", (UINTN)
> BlockDescriptors1);
> +      Print (L"CapsuleApp: capsule data starts          at 0x%X with size 0x%X\n",
> (UINTN) CapsuleBuffer, FileSize);
> +    }
> +
> +    //
> +    // Record descirptor header
> +    //
> +    if (Index == 0) {
> +      BlockDescriptorsHeader = BlockDescriptors1;
> +    }
> +
> +    if (BlockDescriptorPre != NULL) {
> +      BlockDescriptorPre->Union.ContinuationPointer = (UINTN) BlockDescriptors1;
> +      BlockDescriptorPre->Length = 0;
> +    }
> +
> +    //
> +    // Fill them in
> +    //
> +    TempBlockPtr  = BlockDescriptors1;
> +    TempDataPtr   = CapsuleBuffer[Index];
> +    SizeLeft      = FileSize[Index];
> +    for (Number = 0; (Number < Count - 1) && (SizeLeft != 0); Number++) {
> +      //
> +      // Divide remaining data in half
> +      //
> +      if (NumberOfDescriptors != 1) {
> +        if (SizeLeft == 1) {
> +          Size = 1;
> +        } else {
> +          Size = SizeLeft / 2;
> +        }
> +      } else {
> +        Size = SizeLeft;
> +      }
> +      TempBlockPtr->Union.DataBlock    = (UINTN)TempDataPtr;
> +      TempBlockPtr->Length  = Size;
> +      Print (L"CapsuleApp: capsule block/size              0x%X/0x%X\n", (UINTN)
> TempDataPtr, Size);
> +      SizeLeft -= Size;
> +      TempDataPtr += Size;
> +      TempBlockPtr++;
> +    }
> +
> +    //
> +    // Allocate the second list, point the first block's last entry to point
> +    // to this one, and fill this one in. Worst case is that the previous
> +    // list only had one element that pointed here, so we need at least two
> +    // elements -- one to point to all the data, another to terminate the list.
> +    //
> +    if ((NumberOfDescriptors != 1) && (SizeLeft != 0)) {
> +      Count = (INT32)(NumberOfDescriptors + 2) - Count;
> +      if (Count == 1) {
> +        Count++;
> +      }
> +
> +      Size              = Count * sizeof (EFI_CAPSULE_BLOCK_DESCRIPTOR);
> +      BlockDescriptors2 = AllocateRuntimeZeroPool (Size);
> +      if (BlockDescriptors2 == NULL) {
> +        Print (L"CapsuleApp: failed to allocate memory for descriptors\n");
> +        Status = EFI_OUT_OF_RESOURCES;
> +        goto ERREXIT;
> +      }
> +
> +      //
> +      // Point the first list's last element to point to this second list.
> +      //
> +      TempBlockPtr->Union.ContinuationPointer   = (UINTN) BlockDescriptors2;
> +
> +      TempBlockPtr->Length  = 0;
> +      TempBlockPtr = BlockDescriptors2;
> +      for (Number = 0; Number < Count - 1; Number++) {
> +        //
> +        // If second-to-last one, then dump rest to this element
> +        //
> +        if (Number == (Count - 2)) {
> +          Size = SizeLeft;
> +        } else {
> +          //
> +          // Divide remaining data in half
> +          //
> +          if (SizeLeft == 1) {
> +            Size = 1;
> +          } else {
> +            Size = SizeLeft / 2;
> +          }
> +        }
> +
> +        TempBlockPtr->Union.DataBlock    = (UINTN)TempDataPtr;
> +        TempBlockPtr->Length  = Size;
> +        Print (L"CapsuleApp: capsule block/size              0x%X/0x%X\n", (UINTN)
> TempDataPtr, Size);
> +        SizeLeft -= Size;
> +        TempDataPtr += Size;
> +        TempBlockPtr++;
> +        if (SizeLeft == 0) {
> +          break;
> +        }
> +      }
> +    }
> +
> +    BlockDescriptorPre = TempBlockPtr;
> +    BlockDescriptors1  = NULL;
> +  }
> +
> +  //
> +  // Null-terminate.
> +  //
> +  if (TempBlockPtr != NULL) {
> +    TempBlockPtr->Union.ContinuationPointer    = (UINTN)NULL;
> +    TempBlockPtr->Length  = 0;
> +    *BlockDescriptors = BlockDescriptorsHeader;
> +  }
> +
> +  return EFI_SUCCESS;
> +
> +ERREXIT:
> +  if (BlockDescriptors1 != NULL) {
> +    FreePool(BlockDescriptors1);
> +  }
> +
> +  if (BlockDescriptors2 != NULL) {
> +    FreePool(BlockDescriptors2);
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  Clear the Gather list for a list of capsule images.
> +
> +  @param[in]  BlockDescriptors The block descriptors for the capsule images
> +  @param[in]  CapsuleNum       The count of capsule images
> +**/
> +VOID
> +CleanGatherList(
> +  IN EFI_CAPSULE_BLOCK_DESCRIPTOR   *BlockDescriptors,
> +  IN UINTN                          CapsuleNum
> +  )
> +{
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR   *TempBlockPtr;
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR   *TempBlockPtr1;
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR   *TempBlockPtr2;
> +  UINTN                          Index;
> +
> +  if (BlockDescriptors != NULL) {
> +    TempBlockPtr1 = BlockDescriptors;
> +    while (1){
> +      TempBlockPtr = TempBlockPtr1;
> +      for (Index = 0; Index < CapsuleNum; Index++) {
> +        if (TempBlockPtr[Index].Length == 0) {
> +          break;
> +        }
> +      }
> +
> +      if (TempBlockPtr[Index].Union.ContinuationPointer == (UINTN)NULL) {
> +        break;
> +      }
> +
> +      TempBlockPtr2 = (VOID *) ((UINTN) TempBlockPtr->Union.ContinuationPointer);
> +      FreePool(TempBlockPtr1);
> +      TempBlockPtr1 = TempBlockPtr2;
> +    }
> +  }
> +}
> +
> +/**
> +  Print APP usage.
> +**/
> +VOID
> +PrintUsage (
> +  VOID
> +  )
> +{
> +  Print(L"CapsuleApp:  usage\n");
> +  Print(L"  CapsuleApp [-F] <Capsule...> [-NR]\n");
> +  Print(L"  CapsuleApp -S\n");
> +  Print(L"  CapsuleApp -C\n");
> +  Print(L"  CapsuleApp -P\n");
> +  Print(L"  CapsuleApp -E\n");
> +  Print(L"  CapsuleApp -G <BMP> -O <Capsule>\n");
> +  Print(L"  CapsuleApp -N <Capsule> -O <NestedCapsule>\n");
> +  Print(L"  CapsuleApp -D|-DS <Capsule>\n");
> +  Print(L"Parameter:\n");
> +  Print(L"  -F:  Put capsule file to disk.\n");
> +  Print(L"       No -F means to put capsule file in memory.\n");
> +  Print(L"  -NR: No Reset.\n");
> +  Print(L"  -S:  Dump capsule status.\n");
> +  Print(L"  -C:  Clear capsule status.\n");
> +  Print(L"  -P:  Dump FMP protocol info.\n");
> +  Print(L"  -E:  Dump ESRT table info.\n");
> +  Print(L"  -G:  Input BMP file name\n");
> +  Print(L"  -N:  Append Capsule Header accroding to Windows Firmware Update\n");
> +  Print(L"  -O:  Output Capsule file name\n");
> +  Print(L"  -D:  Dump Capsule\n");
> +  Print(L"  -DS: Dump Capsule with System FMP format\n");
> +}
> +
> +/**
> +  Update Capsule image.
> +
> +  @param[in]  ImageHandle     The image handle.
> +  @param[in]  SystemTable     The system table.
> +
> +  @retval EFI_SUCCESS            Command completed successfully.
> +  @retval EFI_INVALID_PARAMETER  Command usage error.
> +  @retval EFI_NOT_FOUND          The input file can't be found.
> +**/
> +EFI_STATUS
> +EFIAPI
> +UefiMain (
> +  IN EFI_HANDLE        ImageHandle,
> +  IN EFI_SYSTEM_TABLE  *SystemTable
> +  )
> +{
> +  EFI_STATUS                    Status;
> +  UINTN                         FileSize[MAX_CAPSULE_NUM];
> +  VOID                          *CapsuleBuffer[MAX_CAPSULE_NUM];
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR  *BlockDescriptors;
> +  EFI_CAPSULE_HEADER             *CapsuleHeaderArray[MAX_CAPSULE_NUM + 1];
> +  UINT64                         MaxCapsuleSize;
> +  EFI_RESET_TYPE                 ResetType;
> +  BOOLEAN                        NeedReset;
> +  BOOLEAN                        NoReset;
> +  BOOLEAN                        NeedCopyOnDisk;
> +  CHAR16                         *CapsuleName;
> +  UINTN                          CapsuleNum;
> +  UINTN                          Index;
> +
> +  Status = GetArg();
> +  if (EFI_ERROR(Status)) {
> +    PrintUsage();
> +    return Status;
> +  }
> +  if (Argc < 2) {
> +    PrintUsage();
> +    CleanArg();
> +    return EFI_INVALID_PARAMETER;
> +  }
> +  if ((StrCmp(Argv[1], L"-D") == 0) ||
> +      (StrCmp(Argv[1], L"-DS") == 0)) {
> +    Status = DumpCapsule();
> +    CleanArg();
> +    return Status;
> +  }
> +  if (StrCmp(Argv[1], L"-G") == 0) {
> +    Status = CreateBmpFmp();
> +    CleanArg();
> +    return Status;
> +  }
> +  if (StrCmp(Argv[1], L"-N") == 0) {
> +    Status = CreateNestedFmp();
> +    CleanArg();
> +    return Status;
> +  }
> +  if (StrCmp(Argv[1], L"-S") == 0) {
> +    Status = DmpCapsuleStatusVariable();
> +    CleanArg();
> +    return EFI_SUCCESS;
> +  }
> +  if (StrCmp(Argv[1], L"-C") == 0) {
> +    Status = ClearCapsuleStatusVariable();
> +    CleanArg();
> +    return Status;
> +  }
> +  if (StrCmp(Argv[1], L"-P") == 0) {
> +    DumpFmpData();
> +    CleanArg();
> +    return EFI_SUCCESS;
> +  }
> +  if (StrCmp(Argv[1], L"-E") == 0) {
> +    DumpEsrtData();
> +    CleanArg();
> +    return EFI_SUCCESS;
> +  }
> +  if (StrCmp(Argv[1], L"-F") == 0) {
> +    NeedCopyOnDisk = TRUE;
> +    CapsuleFirstIndex = 2;
> +  } else {
> +    NeedCopyOnDisk = FALSE;
> +    CapsuleFirstIndex = 1;
> +  }
> +  if (StrCmp(Argv[Argc - 1], L"-NR") == 0) {
> +    NoReset = TRUE;
> +    CapsuleLastIndex = Argc - 2;
> +  } else {
> +    NoReset = FALSE;
> +    CapsuleLastIndex = Argc - 1;
> +  }
> +  CapsuleNum = CapsuleLastIndex - CapsuleFirstIndex + 1;
> +
> +  if (CapsuleFirstIndex > CapsuleLastIndex) {
> +    Print(L"CapsuleApp: NO capsule image.\n");
> +    CleanArg();
> +    return EFI_UNSUPPORTED;
> +  }
> +  if (CapsuleNum > MAX_CAPSULE_NUM) {
> +    Print(L"CapsuleApp: Too many capsule images.\n");
> +    CleanArg();
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  ZeroMem(&CapsuleBuffer, sizeof(CapsuleBuffer));
> +  ZeroMem(&FileSize, sizeof(FileSize));
> +  BlockDescriptors = NULL;
> +
> +  for (Index = 0; Index < CapsuleNum; Index++) {
> +    CapsuleName = Argv[CapsuleFirstIndex + Index];
> +    Status = ReadFileToBuffer(CapsuleName, &FileSize[Index], &CapsuleBuffer[Index]);
> +    if (EFI_ERROR(Status)) {
> +      Print(L"CapsuleApp: capsule image (%s) is not found.\n", CapsuleName);
> +      goto Done;
> +    }
> +  }
> +
> +  if (NeedCopyOnDisk) {
> +    Status = CopyCapsuleToActiveEfiPartition(CapsuleBuffer, FileSize, CapsuleNum);
> +  } else {
> +    //
> +    // Every capsule use 2 descriptor 1 for data 1 for end
> +    //
> +    Status = BuildGatherList(CapsuleBuffer, FileSize, CapsuleNum, &BlockDescriptors);
> +  }
> +  if (EFI_ERROR(Status)) {
> +    goto Done;
> +  }
> +
> +  //
> +  // Call the runtime service capsule.
> +  //
> +  NeedReset = FALSE;
> +  for (Index = 0; Index < CapsuleNum; Index++) {
> +    CapsuleHeaderArray[Index] = (EFI_CAPSULE_HEADER *) CapsuleBuffer[Index];
> +    if ((CapsuleHeaderArray[Index]->Flags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET) != 0)
> {
> +      NeedReset = TRUE;
> +    }
> +  }
> +  CapsuleHeaderArray[CapsuleNum] = NULL;
> +  if (NoReset) {
> +    NeedReset = FALSE;
> +  }
> +
> +  //
> +  // Inquire platform capability of UpdateCapsule.
> +  //
> +  Status = gRT->QueryCapsuleCapabilities (CapsuleHeaderArray, CapsuleNum,
> &MaxCapsuleSize, &ResetType);
> +  if (EFI_ERROR(Status)) {
> +    Print (L"CapsuleApp: failed to query capsule capability - %r\n", Status);
> +    goto Done;
> +  }
> +
> +  for (Index = 0; Index < CapsuleNum; Index++) {
> +    if (FileSize[Index] > MaxCapsuleSize) {
> +      Print (L"CapsuleApp: capsule is too large to update, %ld is allowed\n",
> MaxCapsuleSize);
> +      Status = EFI_UNSUPPORTED;
> +      goto Done;
> +    }
> +  }
> +
> +  //
> +  // Check whether the input capsule image has the flag of persist across system
> reset.
> +  //
> +  if (NeedReset) {
> +    Status = gRT->UpdateCapsule(CapsuleHeaderArray,CapsuleNum,(UINTN)
> BlockDescriptors);
> +    if (Status != EFI_SUCCESS) {
> +      Print (L"CapsuleApp: failed to update capsule - %r\n", Status);
> +      goto Done;
> +    }
> +    //
> +    // For capsule who has reset flag, after calling UpdateCapsule service,triger a
> +    // system reset to process capsule persist across a system reset.
> +    //
> +    gRT->ResetSystem (ResetType, EFI_SUCCESS, 0, NULL);
> +  } else {
> +    //
> +    // For capsule who has no reset flag, only call UpdateCapsule Service without a
> +    // system reset. The service will process the capsule immediately.
> +    //
> +    Status = gRT->UpdateCapsule (CapsuleHeaderArray,CapsuleNum,(UINTN)
> BlockDescriptors);
> +    if (Status != EFI_SUCCESS) {
> +      Print (L"CapsuleApp: failed to update capsule - %r\n", Status);
> +    }
> +  }
> +
> +  Status = EFI_SUCCESS;
> +
> +Done:
> +  for (Index = 0; Index < CapsuleNum; Index++) {
> +    if (CapsuleBuffer[Index] != NULL) {
> +      FreePool (CapsuleBuffer[Index]);
> +    }
> +  }
> +
> +  CleanGatherList(BlockDescriptors, CapsuleNum);
> +  CleanArg();
> +
> +  return Status;
> +}
> diff --git a/MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf
> b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf
> new file mode 100644
> index 0000000..7ee44fc
> --- /dev/null
> +++ b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf
> @@ -0,0 +1,71 @@
> +##  @file
> +#  A shell application that triggers capsule update process.
> +#
> +# This application can trigger capsule update process. It can also
> +# generate capsule image, or dump capsule variable information.
> +#
> +#  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
> +#  This program and the accompanying materials
> +#  are licensed and made available under the terms and conditions of the BSD License
> +#  which accompanies this distribution.  The full text of the license may be found at
> +#  http://opensource.org/licenses/bsd-license.php
> +#
> +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +#
> +##
> +
> +[Defines]
> +  INF_VERSION                    = 0x00010006
> +  BASE_NAME                      = CapsuleApp
> +  MODULE_UNI_FILE                = CapsuleApp.uni
> +  FILE_GUID                      = 4CEF31DA-8682-4274-9CC4-AEE7516A5E7B
> +  MODULE_TYPE                    = UEFI_APPLICATION
> +  VERSION_STRING                 = 1.0
> +  ENTRY_POINT                    = UefiMain
> +
> +#
> +# The following information is for reference only and not required by the build tools.
> +#
> +#  VALID_ARCHITECTURES           = IA32 X64
> +#
> +
> +[Sources]
> +  CapsuleApp.c
> +  CapsuleDump.c
> +  AppSupport.c
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +
> +[Guids]
> +  gEfiFileInfoGuid
> +  gEfiPartTypeSystemPartGuid
> +  gEfiGlobalVariableGuid
> +  gEfiCapsuleReportGuid
> +  gEfiFmpCapsuleGuid
> +  gWindowsUxCapsuleGuid
> +  gEfiCertTypeRsa2048Sha256Guid
> +  gEfiCertPkcs7Guid
> +  gEfiSystemResourceTableGuid
> +
> +[Protocols]
> +  gEfiLoadedImageProtocolGuid
> +  gEfiSimpleFileSystemProtocolGuid
> +  gEfiGraphicsOutputProtocolGuid
> +  gEfiFirmwareManagementProtocolGuid
> +
> +[LibraryClasses]
> +  BaseLib
> +  UefiApplicationEntryPoint
> +  DebugLib
> +  MemoryAllocationLib
> +  UefiBootServicesTableLib
> +  UefiRuntimeServicesTableLib
> +  UefiLib
> +  PrintLib
> +  EdkiiSystemCapsuleLib
> +
> +[UserExtensions.TianoCore."ExtraFiles"]
> +  CapsuleAppExtra.uni
> diff --git a/MdeModulePkg/Application/CapsuleApp/CapsuleApp.uni
> b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.uni
> new file mode 100644
> index 0000000..54d6e12
> --- /dev/null
> +++ b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.uni
> @@ -0,0 +1,22 @@
> +// /** @file
> +// A shell application that triggers capsule update process.
> +//
> +// This application can trigger capsule update process. It can also
> +// generate capsule image, or dump capsule variable information.
> +//
> +// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
> +//
> +// This program and the accompanying materials
> +// are licensed and made available under the terms and conditions of the BSD License
> +// which accompanies this distribution. The full text of the license may be found at
> +// http://opensource.org/licenses/bsd-license.php
> +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +//
> +// **/
> +
> +
> +#string STR_MODULE_ABSTRACT             #language en-US "A shell application that
> triggers capsule update process."
> +
> +#string STR_MODULE_DESCRIPTION          #language en-US "This application can trigger
> capsule update process. It can also generate capsule image, or dump capsule variable
> information."
> +
> diff --git a/MdeModulePkg/Application/CapsuleApp/CapsuleAppExtra.uni
> b/MdeModulePkg/Application/CapsuleApp/CapsuleAppExtra.uni
> new file mode 100644
> index 0000000..b5a8840
> --- /dev/null
> +++ b/MdeModulePkg/Application/CapsuleApp/CapsuleAppExtra.uni
> @@ -0,0 +1,19 @@
> +// /** @file
> +// CapsuleApp Localized Strings and Content
> +//
> +// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
> +//
> +// This program and the accompanying materials
> +// are licensed and made available under the terms and conditions of the BSD License
> +// which accompanies this distribution. The full text of the license may be found at
> +// http://opensource.org/licenses/bsd-license.php
> +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +//
> +// **/
> +
> +#string STR_PROPERTIES_MODULE_NAME
> +#language en-US
> +"Capsule Application"
> +
> +
> diff --git a/MdeModulePkg/Application/CapsuleApp/CapsuleDump.c
> b/MdeModulePkg/Application/CapsuleApp/CapsuleDump.c
> new file mode 100644
> index 0000000..c56f41f
> --- /dev/null
> +++ b/MdeModulePkg/Application/CapsuleApp/CapsuleDump.c
> @@ -0,0 +1,840 @@
> +/** @file
> +  Dump Capsule image information.
> +
> +  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the BSD License
> +  which accompanies this distribution.  The full text of the license may be found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +
> +**/
> +
> +#include <PiDxe.h>
> +#include <Library/BaseLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/UefiRuntimeServicesTableLib.h>
> +#include <Library/UefiLib.h>
> +#include <Library/PrintLib.h>
> +#include <Library/EdkiiSystemCapsuleLib.h>
> +#include <Protocol/FirmwareManagement.h>
> +#include <Guid/ImageAuthentication.h>
> +#include <Guid/EdkiiSystemFmpCapsule.h>
> +#include <Guid/CapsuleReport.h>
> +#include <Guid/SystemResourceTable.h>
> +#include <Guid/FmpCapsule.h>
> +#include <IndustryStandard/WindowsUxCapsule.h>
> +
> +/**
> +  Read a file.
> +
> +  @param FileName        The file to be read.
> +  @param BufferSize      The file buffer size
> +  @param Buffer          The file buffer
> +
> +  @retval EFI_SUCCESS    Read file successfully
> +  @retval EFI_NOT_FOUND  File not found
> +**/
> +EFI_STATUS
> +ReadFileToBuffer(
> +  IN  CHAR16                               *FileName,
> +  OUT UINTN                                *BufferSize,
> +  OUT VOID                                 **Buffer
> +  );
> +
> +extern UINTN  Argc;
> +extern CHAR16 *Argv[];
> +
> +/**
> +  Dump UX capsule information.
> +
> +  @param CapsuleHeader      The UX capsule header
> +**/
> +VOID
> +DumpUxCapsule(
> +  IN EFI_CAPSULE_HEADER  *CapsuleHeader
> +  )
> +{
> +  EFI_DISPLAY_CAPSULE                           *DisplayCapsule;
> +  DisplayCapsule = (EFI_DISPLAY_CAPSULE *)CapsuleHeader;
> +  Print(L"[UxCapusule]\n");
> +  Print(L"CapsuleHeader:\n");
> +  Print(L"  CapsuleGuid      - %g\n", &DisplayCapsule->CapsuleHeader.CapsuleGuid);
> +  Print(L"  HeaderSize       - 0x%x\n", DisplayCapsule->CapsuleHeader.HeaderSize);
> +  Print(L"  Flags            - 0x%x\n", DisplayCapsule->CapsuleHeader.Flags);
> +  Print(L"  CapsuleImageSize - 0x%x\n", DisplayCapsule-
> >CapsuleHeader.CapsuleImageSize);
> +  Print(L"ImagePayload:\n");
> +  Print(L"  Version          - 0x%x\n", DisplayCapsule->ImagePayload.Version);
> +  Print(L"  Checksum         - 0x%x\n", DisplayCapsule->ImagePayload.Checksum);
> +  Print(L"  ImageType        - 0x%x\n", DisplayCapsule->ImagePayload.ImageType);
> +  Print(L"  Mode             - 0x%x\n", DisplayCapsule->ImagePayload.Mode);
> +  Print(L"  OffsetX          - 0x%x\n", DisplayCapsule->ImagePayload.OffsetX);
> +  Print(L"  OffsetY          - 0x%x\n", DisplayCapsule->ImagePayload.OffsetY);
> +}
> +
> +/**
> +  Dump FMP image authentication information.
> +
> +  @param Image      The FMP capsule image
> +  @param ImageSize  The size of the FMP capsule image in bytes.
> +
> +  @return the size of FMP authentication.
> +**/
> +UINTN
> +DumpImageAuthentication(
> +  IN VOID   *Image,
> +  IN UINTN  ImageSize
> +  )
> +{
> +  EFI_FIRMWARE_IMAGE_AUTHENTICATION             *ImageAuthentication;
> +
> +  ImageAuthentication = Image;
> +  if (CompareGuid(&ImageAuthentication->AuthInfo.CertType, &gEfiCertPkcs7Guid) ||
> +      CompareGuid(&ImageAuthentication->AuthInfo.CertType,
> &gEfiCertTypeRsa2048Sha256Guid)) {
> +    Print(L"[ImageAuthentication]\n");
> +    Print(L"  MonotonicCount   - 0x%lx\n", ImageAuthentication->MonotonicCount);
> +    Print(L"WIN_CERTIFICATE:\n");
> +    Print(L"  dwLength         - 0x%x\n", ImageAuthentication->AuthInfo.Hdr.dwLength);
> +    Print(L"  wRevision        - 0x%x\n", ImageAuthentication-
> >AuthInfo.Hdr.wRevision);
> +    Print(L"  wCertificateType - 0x%x\n", ImageAuthentication-
> >AuthInfo.Hdr.wCertificateType);
> +    Print(L"  CertType         - %g\n", &ImageAuthentication->AuthInfo.CertType);
> +    return sizeof(ImageAuthentication->MonotonicCount) + ImageAuthentication-
> >AuthInfo.Hdr.dwLength;
> +  } else {
> +    return 0;
> +  }
> +}
> +
> +/**
> +  Dump EDKII system FMP capsule.
> +
> +  @param Image      The EDKII system FMP capsule.
> +  @param ImageSize  The size of the EDKII system FMP capsule in bytes.
> +**/
> +VOID
> +DumpEdkiiSystemFmpCapsule(
> +  IN VOID   *Image,
> +  IN UINTN  ImageSize
> +  )
> +{
> +  UINTN                                         ImageOffset;
> +  VOID                                          *BiosImage;
> +  UINTN                                         BiosImageSize;
> +  BOOLEAN                                       Result;
> +  EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR        *TempImageFmpInfo;
> +  EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR        *ImageFmpInfo;
> +  UINTN                                         ImageFmpInfoSize;
> +
> +  //
> +  // We do not know if there is EFI_FIRMWARE_IMAGE_AUTHENTICATION.
> +  // so just *try* to parse it
> +  //
> +  ImageOffset = DumpImageAuthentication(Image, ImageSize);
> +  Image = (UINT8 *)Image + ImageOffset;
> +  ImageSize -= ImageOffset;
> +  Print(L"[Image]\n");
> +  Print(L"  ImageSize   - 0x%x\n", ImageSize);
> +
> +  Result = ExtractConfigImage(Image, ImageSize, &BiosImage, &BiosImageSize);
> +  if (Result) {
> +    Print(L"  ConfigFileSize  - 0x%x\n", BiosImageSize);
> +  }
> +  Result = ExtractDriverFvImage(Image, ImageSize, &BiosImage, &BiosImageSize);
> +  if (Result) {
> +    Print(L"  DriverFvSize    - 0x%x\n", BiosImageSize);
> +  }
> +  Result = ExtractSystemFirmwareImage(Image, ImageSize, &BiosImage, &BiosImageSize);
> +  if (Result) {
> +    Print(L"  BiosImageSize   - 0x%x\n", BiosImageSize);
> +  }
> +  Result = ExtractSystemFirmwareImageFmpInfo(BiosImage, BiosImageSize,
> &TempImageFmpInfo, &ImageFmpInfoSize);
> +  if (Result) {
> +    ImageFmpInfo = AllocateCopyPool(ImageFmpInfoSize, TempImageFmpInfo);
> +    if (ImageFmpInfo != NULL) {
> +      Print(L"[ImageFmpInfo]\n");
> +      Print(L"  Signature                      - 0x%x\n", ImageFmpInfo->Signature);
> +      Print(L"  HeaderLength                   - 0x%x\n", ImageFmpInfo->HeaderLength);
> +      Print(L"  Length                         - 0x%x\n", ImageFmpInfo->Length);
> +      Print(L"  PackageVersion                 - 0x%x\n", ImageFmpInfo-
> >PackageVersion);
> +      Print(L"  PackageVersionNameStringOffset - 0x%x\n", ImageFmpInfo-
> >PackageVersionNameStringOffset);
> +      if (ImageFmpInfo->PackageVersionNameStringOffset != 0) {
> +        Print(L"                                 - %s\n", (UINT8 *)ImageFmpInfo +
> ImageFmpInfo->PackageVersionNameStringOffset);
> +      }
> +      Print(L"  ImageIndex                     - 0x%x\n", ImageFmpInfo->ImageIndex);
> +      Print(L"  ImageTypeId                    - %g\n", &ImageFmpInfo->ImageTypeId);
> +      Print(L"  ImageId                        - 0x%lx\n", ImageFmpInfo->ImageId);
> +      Print(L"  ImageIdNameStringOffset        - 0x%x\n", ImageFmpInfo-
> >ImageIdNameStringOffset);
> +      if (ImageFmpInfo->ImageIdNameStringOffset != 0) {
> +        Print(L"                                 - %s\n", (UINT8 *)ImageFmpInfo +
> ImageFmpInfo->ImageIdNameStringOffset);
> +      }
> +      Print(L"  Version                        - 0x%x\n", ImageFmpInfo->Version);
> +      Print(L"  VersionNameStringOffset        - 0x%x\n", ImageFmpInfo-
> >VersionNameStringOffset);
> +      if (ImageFmpInfo->VersionNameStringOffset != 0) {
> +        Print(L"                                 - %s\n", (UINT8 *)ImageFmpInfo +
> ImageFmpInfo->VersionNameStringOffset);
> +      }
> +      Print(L"  Size                           - 0x%lx\n", ImageFmpInfo->Size);
> +      Print(L"  AttributesSupported            - 0x%lx\n", ImageFmpInfo-
> >AttributesSupported);
> +      Print(L"  AttributesSetting              - 0x%lx\n", ImageFmpInfo-
> >AttributesSetting);
> +      Print(L"  Compatibilities                - 0x%lx\n", ImageFmpInfo-
> >Compatibilities);
> +      Print(L"  LowestSupportedImageVersion    - 0x%x\n", ImageFmpInfo-
> >LowestSupportedImageVersion);
> +      Print(L"  LastAttemptVersion             - 0x%x\n", ImageFmpInfo-
> >LastAttemptVersion);
> +      Print(L"  LastAttemptStatus              - 0x%x\n", ImageFmpInfo-
> >LastAttemptStatus);
> +      Print(L"  HardwareInstance               - 0x%lx\n", ImageFmpInfo-
> >HardwareInstance);
> +      Print(L"  Version                        - 0x%x\n", ImageFmpInfo->Version);
> +      FreePool(ImageFmpInfo);
> +    }
> +  }
> +}
> +
> +/**
> +  Dump a non-nested FMP capsule.
> +
> +  @param  CapsuleHeader  A pointer to CapsuleHeader
> +  @param  IsSystemFmp    If it is a system FMP
> +**/
> +VOID
> +DumpFmpCapsule(
> +  IN EFI_CAPSULE_HEADER  *CapsuleHeader,
> +  IN BOOLEAN             IsSystemFmp
> +  )
> +{
> +  EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER        *FmpCapsuleHeader;
> +  UINT64                                        *ItemOffsetList;
> +  UINTN                                         Index;
> +  UINTN                                         Count;
> +  EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER  *FmpImageHeader;
> +  VOID                                          *Image;
> +
> +  Print(L"[FmpCapusule]\n");
> +  Print(L"CapsuleHeader:\n");
> +  Print(L"  CapsuleGuid      - %g\n", &CapsuleHeader->CapsuleGuid);
> +  Print(L"  HeaderSize       - 0x%x\n", CapsuleHeader->HeaderSize);
> +  Print(L"  Flags            - 0x%x\n", CapsuleHeader->Flags);
> +  Print(L"  CapsuleImageSize - 0x%x\n", CapsuleHeader->CapsuleImageSize);
> +
> +  FmpCapsuleHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *)((UINT8 *)CapsuleHeader
> + CapsuleHeader->HeaderSize);
> +  ItemOffsetList = (UINT64 *)(FmpCapsuleHeader + 1);
> +  Print(L"FmpHeader:\n");
> +  Print(L"  Version             - 0x%x\n", FmpCapsuleHeader->Version);
> +  Print(L"  EmbeddedDriverCount - 0x%x\n", FmpCapsuleHeader->EmbeddedDriverCount);
> +  Print(L"  PayloadItemCount    - 0x%x\n", FmpCapsuleHeader->PayloadItemCount);
> +  Count = FmpCapsuleHeader->EmbeddedDriverCount + FmpCapsuleHeader->PayloadItemCount;
> +  for (Index = 0; Index < Count; Index++) {
> +    Print(L"  Offset[%d]           - 0x%x\n", Index, ItemOffsetList[Index]);
> +  }
> +
> +  for (Index = FmpCapsuleHeader->EmbeddedDriverCount; Index < Count; Index++) {
> +    Print(L"FmpPayload[%d] ImageHeader:\n", Index);
> +    FmpImageHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *)((UINT8
> *)FmpCapsuleHeader + ItemOffsetList[Index]);
> +    Print(L"  Version                - 0x%x\n", FmpImageHeader->Version);
> +    Print(L"  UpdateImageTypeId      - %g\n", &FmpImageHeader->UpdateImageTypeId);
> +    Print(L"  UpdateImageIndex       - 0x%x\n", FmpImageHeader->UpdateImageIndex);
> +    Print(L"  UpdateImageSize        - 0x%x\n", FmpImageHeader->UpdateImageSize);
> +    Print(L"  UpdateVendorCodeSize   - 0x%x\n", FmpImageHeader->UpdateVendorCodeSize);
> +    if (FmpImageHeader->Version >=
> EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {
> +      Print(L"  UpdateHardwareInstance - 0x%lx\n", FmpImageHeader-
> >UpdateHardwareInstance);
> +    }
> +    if (FmpImageHeader->Version >=
> EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {
> +      Image = (UINT8 *)(FmpImageHeader + 1);
> +    }  else {
> +      Image = (UINT8 *)FmpImageHeader +
> OFFSET_OF(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER, UpdateHardwareInstance);
> +    }
> +    if (IsSystemFmp) {
> +      DumpEdkiiSystemFmpCapsule(Image, FmpImageHeader->UpdateImageSize);
> +    }
> +  }
> +}
> +
> +/**
> +  Return if there is a FMP header below capsule header.
> +
> +  @param[in] CapsuleHeader A pointer to EFI_CAPSULE_HEADER
> +
> +  @retval TRUE  There is a FMP header below capsule header.
> +  @retval FALSE There is not a FMP header below capsule header
> +**/
> +BOOLEAN
> +IsNestedFmpCapsule(
> +  IN EFI_CAPSULE_HEADER         *CapsuleHeader
> +  )
> +{
> +  EFI_STATUS                 Status;
> +  EFI_SYSTEM_RESOURCE_TABLE  *Esrt;
> +  EFI_SYSTEM_RESOURCE_ENTRY  *EsrtEntry;
> +  UINTN                      Index;
> +  BOOLEAN                    EsrtGuidFound;
> +  EFI_CAPSULE_HEADER         *NestedCapsuleHeader;
> +  UINTN                      NestedCapsuleSize;
> +
> +  //
> +  // Check ESRT
> +  //
> +  EsrtGuidFound = FALSE;
> +  Status = EfiGetSystemConfigurationTable(&gEfiSystemResourceTableGuid, (VOID
> **)&Esrt);
> +  if (!EFI_ERROR(Status)) {
> +    EsrtEntry = (VOID *)(Esrt + 1);
> +    for (Index = 0; Index < Esrt->FwResourceCount; Index++, EsrtEntry++) {
> +      if (CompareGuid(&EsrtEntry->FwClass, &CapsuleHeader->CapsuleGuid)) {
> +        EsrtGuidFound = TRUE;
> +        break;
> +      }
> +    }
> +  }
> +
> +  if (!EsrtGuidFound) {
> +    return FALSE;
> +  }
> +
> +  //
> +  // Check nested capsule header
> +  // FMP GUID after ESRT one
> +  //
> +  NestedCapsuleHeader = (EFI_CAPSULE_HEADER *)((UINT8 *)CapsuleHeader + CapsuleHeader-
> >HeaderSize);
> +  NestedCapsuleSize = (UINTN)CapsuleHeader + CapsuleHeader->HeaderSize -
> (UINTN)NestedCapsuleHeader;
> +  if (NestedCapsuleSize < sizeof(EFI_CAPSULE_HEADER)) {
> +    return FALSE;
> +  }
> +  if (!CompareGuid(&NestedCapsuleHeader->CapsuleGuid, &gEfiFmpCapsuleGuid)) {
> +    return FALSE;
> +  }
> +  return TRUE;
> +}
> +
> +/**
> +  Dump capsule information
> +
> +  @retval EFI_SUCCESS            The capsule information is dumped.
> +  @retval EFI_UNSUPPORTED        Input parameter is not valid.
> +**/
> +EFI_STATUS
> +DumpCapsule(
> +  VOID
> +  )
> +{
> +  CHAR16                                        *CapsuleName;
> +  VOID                                          *Buffer;
> +  UINTN                                         FileSize;
> +  BOOLEAN                                       IsSystemFmp;
> +  EFI_CAPSULE_HEADER                            *CapsuleHeader;
> +  EFI_STATUS                                    Status;
> +
> +  if (Argc != 3) {
> +    Print(L"CapsuleApp: Invalid Parameter.\n");
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  IsSystemFmp = FALSE;
> +  if (StrCmp(Argv[1], L"-DS") == 0) {
> +    IsSystemFmp = TRUE;
> +  }
> +
> +  CapsuleName = Argv[2];
> +  Status = ReadFileToBuffer(CapsuleName, &FileSize, &Buffer);
> +  if (EFI_ERROR(Status)) {
> +    Print(L"CapsuleApp: Capsule (%s) is not found.\n", CapsuleName);
> +    goto Done;
> +  }
> +
> +  CapsuleHeader = Buffer;
> +  if (CompareGuid(&CapsuleHeader->CapsuleGuid, &gWindowsUxCapsuleGuid)) {
> +    DumpUxCapsule(CapsuleHeader);
> +    Status = EFI_SUCCESS;
> +    goto Done;
> +  }
> +
> +  if (CompareGuid(&CapsuleHeader->CapsuleGuid, &gEfiFmpCapsuleGuid)) {
> +    DumpFmpCapsule(CapsuleHeader, IsSystemFmp);
> +  }
> +  if (IsNestedFmpCapsule(CapsuleHeader)) {
> +    Print(L"[NestedCapusule]\n");
> +    Print(L"CapsuleHeader:\n");
> +    Print(L"  CapsuleGuid      - %g\n", &CapsuleHeader->CapsuleGuid);
> +    Print(L"  HeaderSize       - 0x%x\n", CapsuleHeader->HeaderSize);
> +    Print(L"  Flags            - 0x%x\n", CapsuleHeader->Flags);
> +    Print(L"  CapsuleImageSize - 0x%x\n", CapsuleHeader->CapsuleImageSize);
> +    DumpFmpCapsule((EFI_CAPSULE_HEADER *)((UINTN)CapsuleHeader + CapsuleHeader-
> >HeaderSize), IsSystemFmp);
> +  }
> +
> +Done:
> +  FreePool(Buffer);
> +  return Status;
> +}
> +
> +/**
> +  Dump capsule status variable.
> +
> +  @retval EFI_SUCCESS            The capsule status variable is dumped.
> +  @retval EFI_UNSUPPORTED        Input parameter is not valid.
> +**/
> +EFI_STATUS
> +DmpCapsuleStatusVariable(
> +  VOID
> +  )
> +{
> +  EFI_STATUS                          Status;
> +  UINT32                              Index;
> +  CHAR16                              CapsuleVarName[20];
> +  CHAR16                              *TempVarName;
> +  EFI_CAPSULE_RESULT_VARIABLE_HEADER  *CapsuleResult;
> +  EFI_CAPSULE_RESULT_VARIABLE_FMP     *CapsuleResultFmp;
> +  UINTN                               CapsuleFileNameSize;
> +  CHAR16                              CapsuleIndexData[12];
> +  CHAR16                              *CapsuleIndex;
> +
> +  Status = GetVariable2(
> +             L"CapsuleMax",
> +             &gEfiCapsuleReportGuid,
> +             (VOID **)&CapsuleIndex,
> +             NULL
> +             );
> +  if (!EFI_ERROR(Status)) {
> +    CopyMem(CapsuleIndexData, CapsuleIndex, 11 * sizeof(CHAR16));
> +    CapsuleIndexData[11] = 0;
> +    Print(L"CapsuleMax - %s\n", CapsuleIndexData);
> +    FreePool(CapsuleIndex);
> +  }
> +  Status = GetVariable2(
> +             L"CapsuleLast",
> +             &gEfiCapsuleReportGuid,
> +             (VOID **)&CapsuleIndex,
> +             NULL
> +             );
> +  if (!EFI_ERROR(Status)) {
> +    CopyMem(CapsuleIndexData, CapsuleIndex, 11 * sizeof(CHAR16));
> +    CapsuleIndexData[11] = 0;
> +    Print(L"CapsuleLast - %s\n", CapsuleIndexData);
> +    FreePool(CapsuleIndex);
> +  }
> +
> +
> +  StrCpyS (CapsuleVarName, sizeof(CapsuleVarName)/sizeof(CapsuleVarName[0]),
> L"Capsule");
> +  TempVarName = CapsuleVarName + StrLen (CapsuleVarName);
> +  Index = 0;
> +
> +  while (TRUE) {
> +    UnicodeSPrint (TempVarName, 5 * sizeof(CHAR16), L"%04x", Index);
> +
> +    Status = GetVariable2 (
> +               CapsuleVarName,
> +               &gEfiCapsuleReportGuid,
> +               (VOID **) &CapsuleResult,
> +               NULL
> +               );
> +    if (Status == EFI_NOT_FOUND) {
> +      break;
> +    } else if (EFI_ERROR(Status)) {
> +      continue;
> +    }
> +
> +    //
> +    // display capsule process status
> +    //
> +    if (CapsuleResult->VariableTotalSize >=
> sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER)) {
> +      Print (L"CapsuleName: %s\n", CapsuleVarName);
> +      Print (L"  Capsule Guid: %g\n", &CapsuleResult->CapsuleGuid);
> +      Print (L"  Capsule ProcessedTime: %t\n", &CapsuleResult->CapsuleProcessed);
> +      Print (L"  Capsule Status: %r\n", CapsuleResult->CapsuleStatus);
> +    }
> +
> +    if (CompareGuid(&CapsuleResult->CapsuleGuid, &gEfiFmpCapsuleGuid)) {
> +      if (CapsuleResult->VariableTotalSize >=
> sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER) + sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP)) {
> +        CapsuleResultFmp = (EFI_CAPSULE_RESULT_VARIABLE_FMP *)(CapsuleResult + 1);
> +        Print(L"  Capsule FMP Version: 0x%x\n", CapsuleResultFmp->Version);
> +        Print(L"  Capsule FMP PayloadIndex: 0x%x\n", CapsuleResultFmp->PayloadIndex);
> +        Print(L"  Capsule FMP UpdateImageIndex: 0x%x\n", CapsuleResultFmp-
> >UpdateImageIndex);
> +        Print(L"  Capsule FMP UpdateImageTypeId: %g\n", &CapsuleResultFmp-
> >UpdateImageTypeId);
> +        if (CapsuleResult->VariableTotalSize >
> sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER) + sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP)) {
> +          Print(L"  Capsule FMP CapsuleFileName: %s\n", (CapsuleResultFmp + 1));
> +          CapsuleFileNameSize = StrSize((CHAR16 *)(CapsuleResultFmp + 1));
> +          if (CapsuleResult->VariableTotalSize >
> sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER) + sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP) +
> CapsuleFileNameSize) {
> +            Print(L"  Capsule FMP CapsuleTarget: %s\n", (UINT8 *)(CapsuleResultFmp +
> 1) + CapsuleFileNameSize);
> +          }
> +        }
> +      }
> +    }
> +
> +    FreePool(CapsuleResult);
> +
> +    Index++;
> +    if (Index > 0xFFFF) {
> +      break;
> +    }
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +CHAR8 *mFwTypeString[] = {
> +  "Unknown",
> +  "SystemFirmware",
> +  "DeviceFirmware",
> +  "UefiDriver",
> +};
> +
> +CHAR8 *mLastAttemptStatusString[] = {
> +  "Success",
> +  "Error: Unsuccessful",
> +  "Error: Insufficient Resources",
> +  "Error: Incorrect Version",
> +  "Error: Invalid Format",
> +  "Error: Auth Error",
> +  "Error: Power Event AC",
> +  "Error: Power Event Battery",
> +};
> +
> +/**
> +  Convert FwType to a string.
> +
> +  @param FwType  FwType in ESRT
> +
> +  @return a string for FwType.
> +**/
> +CHAR8 *
> +FwTypeToString(
> +  IN UINT32 FwType
> +  )
> +{
> +  if (FwType < sizeof(mFwTypeString) / sizeof(mFwTypeString[0])) {
> +    return mFwTypeString[FwType];
> +  } else {
> +    return "Invalid";
> +  }
> +}
> +
> +/**
> +  Convert LastAttemptStatus to a string.
> +
> +  @param LastAttemptStatus  LastAttemptStatus in FMP or ESRT
> +
> +  @return a string for LastAttemptStatus.
> +**/
> +CHAR8 *
> +LastAttemptStatusToString(
> +  IN UINT32 LastAttemptStatus
> +  )
> +{
> +  if (LastAttemptStatus < sizeof(mLastAttemptStatusString) /
> sizeof(mLastAttemptStatusString[0])) {
> +    return mLastAttemptStatusString[LastAttemptStatus];
> +  } else {
> +    return "Error: Unknown";
> +  }
> +}
> +
> +/**
> +  Dump ESRT entry.
> +
> +  @param EsrtEntry  ESRT entry
> +**/
> +VOID
> +DumpEsrtEntry(
> +  IN EFI_SYSTEM_RESOURCE_ENTRY  *EsrtEntry
> +  )
> +{
> +  Print(L"  FwClass                  - %g\n", &EsrtEntry->FwClass);
> +  Print(L"  FwType                   - 0x%x (%a)\n", EsrtEntry->FwType,
> FwTypeToString(EsrtEntry->FwType));
> +  Print(L"  FwVersion                - 0x%x\n", EsrtEntry->FwVersion);
> +  Print(L"  LowestSupportedFwVersion - 0x%x\n", EsrtEntry->LowestSupportedFwVersion);
> +  Print(L"  CapsuleFlags             - 0x%x\n", EsrtEntry->CapsuleFlags);
> +  Print(L"    PERSIST_ACROSS_RESET   - 0x%x\n", EsrtEntry->CapsuleFlags &
> CAPSULE_FLAGS_PERSIST_ACROSS_RESET);
> +  Print(L"    POPULATE_SYSTEM_TABLE  - 0x%x\n", EsrtEntry->CapsuleFlags &
> CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE);
> +  Print(L"    INITIATE_RESET         - 0x%x\n", EsrtEntry->CapsuleFlags &
> CAPSULE_FLAGS_INITIATE_RESET);
> +  Print(L"  LastAttemptVersion       - 0x%x\n", EsrtEntry->LastAttemptVersion);
> +  Print(L"  LastAttemptStatus        - 0x%x (%a)\n", EsrtEntry->LastAttemptStatus,
> LastAttemptStatusToString(EsrtEntry->LastAttemptStatus));
> +}
> +
> +/**
> +  Dump ESRT table.
> +
> +  @param Esrt  ESRT table
> +**/
> +VOID
> +DumpEsrt(
> +  IN EFI_SYSTEM_RESOURCE_TABLE  *Esrt
> +  )
> +{
> +  UINTN                      Index;
> +  EFI_SYSTEM_RESOURCE_ENTRY  *EsrtEntry;
> +
> +  Print(L"EFI_SYSTEM_RESOURCE_TABLE:\n");
> +  Print(L"FwResourceCount    - 0x%x\n", Esrt->FwResourceCount);
> +  Print(L"FwResourceCountMax - 0x%x\n", Esrt->FwResourceCountMax);
> +  Print(L"FwResourceVersion  - 0x%lx\n", Esrt->FwResourceVersion);
> +
> +  EsrtEntry = (VOID *)(Esrt + 1);
> +  for (Index = 0; Index < Esrt->FwResourceCount; Index++) {
> +    Print(L"EFI_SYSTEM_RESOURCE_ENTRY (%d):\n", Index);
> +    DumpEsrtEntry(EsrtEntry);
> +    EsrtEntry++;
> +  }
> +}
> +
> +/**
> +  Dump ESRT info.
> +**/
> +VOID
> +DumpEsrtData (
> +  VOID
> +  )
> +{
> +  EFI_STATUS                 Status;
> +  EFI_SYSTEM_RESOURCE_TABLE  *Esrt;
> +
> +  Print(L"##############\n");
> +  Print(L"# ESRT TABLE #\n");
> +  Print(L"##############\n");
> +
> +  Status = EfiGetSystemConfigurationTable (&gEfiSystemResourceTableGuid, (VOID
> **)&Esrt);
> +  if (EFI_ERROR(Status)) {
> +    Print(L"ESRT - %r\n", Status);
> +    return;
> +  }
> +  DumpEsrt(Esrt);
> +  Print(L"\n");
> +}
> +
> +/**
> +  Dump FMP information.
> +
> +  @param ImageInfoSize       The size of ImageInfo, in bytes.
> +  @param ImageInfo           A pointer to EFI_FIRMWARE_IMAGE_DESCRIPTOR.
> +  @param DescriptorVersion   The version of EFI_FIRMWARE_IMAGE_DESCRIPTOR.
> +  @param DescriptorCount     The count of EFI_FIRMWARE_IMAGE_DESCRIPTOR.
> +  @param DescriptorSize      The size of an individual EFI_FIRMWARE_IMAGE_DESCRIPTOR,
> in bytes.
> +  @param PackageVersion      The version of package.
> +  @param PackageVersionName  The version name of package.
> +**/
> +VOID
> +DumpFmpImageInfo(
> +  IN UINTN                           ImageInfoSize,
> +  IN EFI_FIRMWARE_IMAGE_DESCRIPTOR   *ImageInfo,
> +  IN UINT32                          DescriptorVersion,
> +  IN UINT8                           DescriptorCount,
> +  IN UINTN                           DescriptorSize,
> +  IN UINT32                          PackageVersion,
> +  IN CHAR16                          *PackageVersionName
> +  )
> +{
> +  EFI_FIRMWARE_IMAGE_DESCRIPTOR                 *CurrentImageInfo;
> +  UINTN                                         Index;
> +
> +  Print(L"  DescriptorVersion  - 0x%x\n", DescriptorVersion);
> +  Print(L"  DescriptorCount    - 0x%x\n", DescriptorCount);
> +  Print(L"  DescriptorSize     - 0x%x\n", DescriptorSize);
> +  Print(L"  PackageVersion     - 0x%x\n", PackageVersion);
> +  Print(L"  PackageVersionName - \"%s\"\n", PackageVersionName);
> +  CurrentImageInfo = ImageInfo;
> +  for (Index = 0; Index < DescriptorCount; Index++) {
> +    Print(L"  ImageDescriptor (%d)\n", Index);
> +    Print(L"    ImageIndex                  - 0x%x\n", CurrentImageInfo->ImageIndex);
> +    Print(L"    ImageTypeId                 - %g\n", &CurrentImageInfo->ImageTypeId);
> +    Print(L"    ImageId                     - 0x%lx\n", CurrentImageInfo->ImageId);
> +    Print(L"    ImageIdName                 - \"%s\"\n", CurrentImageInfo-
> >ImageIdName);
> +    Print(L"    Version                     - 0x%x\n", CurrentImageInfo->Version);
> +    Print(L"    VersionName                 - \"%s\"\n", CurrentImageInfo-
> >VersionName);
> +    Print(L"    Size                        - 0x%x\n", CurrentImageInfo->Size);
> +    Print(L"    AttributesSupported         - 0x%lx\n", CurrentImageInfo-
> >AttributesSupported);
> +    Print(L"      IMAGE_UPDATABLE           - 0x%lx\n", CurrentImageInfo-
> >AttributesSupported & IMAGE_ATTRIBUTE_IMAGE_UPDATABLE);
> +    Print(L"      RESET_REQUIRED            - 0x%lx\n", CurrentImageInfo-
> >AttributesSupported & IMAGE_ATTRIBUTE_RESET_REQUIRED);
> +    Print(L"      AUTHENTICATION_REQUIRED   - 0x%lx\n", CurrentImageInfo-
> >AttributesSupported & IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);
> +    Print(L"      IN_USE                    - 0x%lx\n", CurrentImageInfo-
> >AttributesSupported & IMAGE_ATTRIBUTE_IN_USE);
> +    Print(L"      UEFI_IMAGE                - 0x%lx\n", CurrentImageInfo-
> >AttributesSupported & IMAGE_ATTRIBUTE_UEFI_IMAGE);
> +    Print(L"    AttributesSetting           - 0x%lx\n", CurrentImageInfo-
> >AttributesSetting);
> +    Print(L"      IMAGE_UPDATABLE           - 0x%lx\n", CurrentImageInfo-
> >AttributesSetting & IMAGE_ATTRIBUTE_IMAGE_UPDATABLE);
> +    Print(L"      RESET_REQUIRED            - 0x%lx\n", CurrentImageInfo-
> >AttributesSetting & IMAGE_ATTRIBUTE_RESET_REQUIRED);
> +    Print(L"      AUTHENTICATION_REQUIRED   - 0x%lx\n", CurrentImageInfo-
> >AttributesSetting & IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);
> +    Print(L"      IN_USE                    - 0x%lx\n", CurrentImageInfo-
> >AttributesSetting & IMAGE_ATTRIBUTE_IN_USE);
> +    Print(L"      UEFI_IMAGE                - 0x%lx\n", CurrentImageInfo-
> >AttributesSetting & IMAGE_ATTRIBUTE_UEFI_IMAGE);
> +    Print(L"    Compatibilities             - 0x%lx\n", CurrentImageInfo-
> >Compatibilities);
> +    Print(L"      COMPATIB_CHECK_SUPPORTED  - 0x%lx\n", CurrentImageInfo-
> >Compatibilities & IMAGE_COMPATIBILITY_CHECK_SUPPORTED);
> +    if (DescriptorVersion > 1) {
> +      Print(L"    LowestSupportedImageVersion - 0x%x\n", CurrentImageInfo-
> >LowestSupportedImageVersion);
> +      if (DescriptorVersion > 2) {
> +        Print(L"    LastAttemptVersion          - 0x%x\n", CurrentImageInfo-
> >LastAttemptVersion);
> +        Print(L"    LastAttemptStatus           - 0x%x (%a)\n", CurrentImageInfo-
> >LastAttemptStatus, LastAttemptStatusToString(CurrentImageInfo->LastAttemptStatus));
> +        Print(L"    HardwareInstance            - 0x%lx\n", CurrentImageInfo-
> >HardwareInstance);
> +      }
> +    }
> +    //
> +    // Use DescriptorSize to move ImageInfo Pointer to stay compatible with different
> ImageInfo version
> +    //
> +    CurrentImageInfo = (EFI_FIRMWARE_IMAGE_DESCRIPTOR *)((UINT8 *)CurrentImageInfo +
> DescriptorSize);
> +  }
> +}
> +
> +/**
> +  Dump FMP package information.
> +
> +  @param PackageVersion             The version of package.
> +  @param PackageVersionName         The version name of package.
> +  @param PackageVersionNameMaxLen   The maximum length of PackageVersionName.
> +  @param AttributesSupported        Package attributes that are supported by this
> device.
> +  @param AttributesSetting          Package attributes.
> +**/
> +VOID
> +DumpFmpPackageInfo(
> +  IN UINT32                           PackageVersion,
> +  IN CHAR16                           *PackageVersionName,
> +  IN UINT32                           PackageVersionNameMaxLen,
> +  IN UINT64                           AttributesSupported,
> +  IN UINT64                           AttributesSetting
> +  )
> +{
> +  Print(L"  PackageVersion              - 0x%x\n", PackageVersion);
> +  Print(L"  PackageVersionName          - \"%s\"\n", PackageVersionName);
> +  Print(L"  PackageVersionNameMaxLen    - 0x%x\n", PackageVersionNameMaxLen);
> +  Print(L"  AttributesSupported         - 0x%lx\n", AttributesSupported);
> +  Print(L"    IMAGE_UPDATABLE           - 0x%lx\n", AttributesSupported &
> IMAGE_ATTRIBUTE_IMAGE_UPDATABLE);
> +  Print(L"    RESET_REQUIRED            - 0x%lx\n", AttributesSupported &
> IMAGE_ATTRIBUTE_RESET_REQUIRED);
> +  Print(L"    AUTHENTICATION_REQUIRED   - 0x%lx\n", AttributesSupported &
> IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);
> +  Print(L"  AttributesSetting           - 0x%lx\n", AttributesSetting);
> +  Print(L"    IMAGE_UPDATABLE           - 0x%lx\n", AttributesSetting &
> IMAGE_ATTRIBUTE_IMAGE_UPDATABLE);
> +  Print(L"    RESET_REQUIRED            - 0x%lx\n", AttributesSetting &
> IMAGE_ATTRIBUTE_RESET_REQUIRED);
> +  Print(L"    AUTHENTICATION_REQUIRED   - 0x%lx\n", AttributesSetting &
> IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);
> +}
> +
> +/**
> +  Dump FMP protocol info.
> +**/
> +VOID
> +DumpFmpData (
> +  VOID
> +  )
> +{
> +  EFI_STATUS                                    Status;
> +  EFI_FIRMWARE_MANAGEMENT_PROTOCOL              *Fmp;
> +  EFI_HANDLE                                    *HandleBuffer;
> +  UINTN                                         NumberOfHandles;
> +  UINTN                                         Index;
> +  EFI_FIRMWARE_IMAGE_DESCRIPTOR                 *FmpImageInfoBuf;
> +  UINTN                                         ImageInfoSize;
> +  UINT32                                        FmpImageInfoDescriptorVer;
> +  UINT8                                         FmpImageInfoCount;
> +  UINTN                                         DescriptorSize;
> +  UINT32                                        PackageVersion;
> +  CHAR16                                        *PackageVersionName;
> +  UINT32                                        PackageVersionNameMaxLen;
> +  UINT64                                        AttributesSupported;
> +  UINT64                                        AttributesSetting;
> +
> +  Print(L"############\n");
> +  Print(L"# FMP DATA #\n");
> +  Print(L"############\n");
> +  Status = gBS->LocateHandleBuffer (
> +                  ByProtocol,
> +                  &gEfiFirmwareManagementProtocolGuid,
> +                  NULL,
> +                  &NumberOfHandles,
> +                  &HandleBuffer
> +                  );
> +  if (EFI_ERROR(Status)) {
> +    Print(L"FMP protocol - %r\n", EFI_NOT_FOUND);
> +    return;
> +  }
> +
> +  for (Index = 0; Index < NumberOfHandles; Index++) {
> +    Status = gBS->HandleProtocol(
> +                    HandleBuffer[Index],
> +                    &gEfiFirmwareManagementProtocolGuid,
> +                    (VOID **)&Fmp
> +                    );
> +    if (EFI_ERROR(Status)) {
> +      continue;
> +    }
> +
> +    ImageInfoSize = 0;
> +    Status = Fmp->GetImageInfo (
> +                    Fmp,
> +                    &ImageInfoSize,
> +                    NULL,
> +                    NULL,
> +                    NULL,
> +                    NULL,
> +                    NULL,
> +                    NULL
> +                    );
> +    if (Status != EFI_BUFFER_TOO_SMALL) {
> +      continue;
> +    }
> +
> +    FmpImageInfoBuf = NULL;
> +    FmpImageInfoBuf = AllocateZeroPool (ImageInfoSize);
> +    if (FmpImageInfoBuf == NULL) {
> +      Status = EFI_OUT_OF_RESOURCES;
> +      goto EXIT;
> +    }
> +
> +    PackageVersionName = NULL;
> +    Status = Fmp->GetImageInfo (
> +                    Fmp,
> +                    &ImageInfoSize,               // ImageInfoSize
> +                    FmpImageInfoBuf,              // ImageInfo
> +                    &FmpImageInfoDescriptorVer,   // DescriptorVersion
> +                    &FmpImageInfoCount,           // DescriptorCount
> +                    &DescriptorSize,              // DescriptorSize
> +                    &PackageVersion,              // PackageVersion
> +                    &PackageVersionName           // PackageVersionName
> +                    );
> +
> +    //
> +    // If FMP GetInformation interface failed, skip this resource
> +    //
> +    if (EFI_ERROR(Status)) {
> +      Print(L"FMP (%d) ImageInfo - %r\n", Index, Status);
> +      FreePool(FmpImageInfoBuf);
> +      continue;
> +    }
> +
> +    Print(L"FMP (%d) ImageInfo:\n", Index);
> +    DumpFmpImageInfo(
> +      ImageInfoSize,               // ImageInfoSize
> +      FmpImageInfoBuf,             // ImageInfo
> +      FmpImageInfoDescriptorVer,   // DescriptorVersion
> +      FmpImageInfoCount,           // DescriptorCount
> +      DescriptorSize,              // DescriptorSize
> +      PackageVersion,              // PackageVersion
> +      PackageVersionName           // PackageVersionName
> +      );
> +
> +    if (PackageVersionName != NULL) {
> +      FreePool(PackageVersionName);
> +    }
> +    FreePool(FmpImageInfoBuf);
> +
> +    //
> +    // Get package info
> +    //
> +    PackageVersionName = NULL;
> +    Status = Fmp->GetPackageInfo (
> +                    Fmp,
> +                    &PackageVersion,              // PackageVersion
> +                    &PackageVersionName,          // PackageVersionName
> +                    &PackageVersionNameMaxLen,    // PackageVersionNameMaxLen
> +                    &AttributesSupported,         // AttributesSupported
> +                    &AttributesSetting            // AttributesSetting
> +                    );
> +    if (EFI_ERROR(Status)) {
> +      Print(L"FMP (%d) PackageInfo - %r\n", Index, Status);
> +    } else {
> +      Print(L"FMP (%d) ImageInfo:\n", Index);
> +      DumpFmpPackageInfo(
> +        PackageVersion,              // PackageVersion
> +        PackageVersionName,          // PackageVersionName
> +        PackageVersionNameMaxLen,    // PackageVersionNameMaxLen
> +        AttributesSupported,         // AttributesSupported
> +        AttributesSetting            // AttributesSetting
> +        );
> +
> +      if (PackageVersionName != NULL) {
> +        FreePool(PackageVersionName);
> +      }
> +    }
> +  }
> +  Print(L"\n");
> +
> +EXIT:
> +  FreePool(HandleBuffer);
> +}
> --
> 2.7.4.windows.1


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

* Re: [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application.
  2016-09-29  2:37     ` Yao, Jiewen
@ 2016-09-29  6:39       ` Ni, Ruiyu
  2016-09-29 19:10         ` Carsey, Jaben
  0 siblings, 1 reply; 83+ messages in thread
From: Ni, Ruiyu @ 2016-09-29  6:39 UTC (permalink / raw)
  To: Yao, Jiewen, Kinney, Michael D, edk2-devel@lists.01.org
  Cc: Tian, Feng, Zhang, Chao B, Gao, Liming, Zeng, Star, Carsey, Jaben

Jiewen,
The way CapsuleApp extracts the ARGV assumes UEFI Shell encodes the parameters using a certain way. But the parameter encoding way is not described in the Shell spec.
Maybe we can put the CapsuleApp in ShellPkg, then let it directly use ShellParameter protocol to get the ARGV.

Copying Jaben.

Regards,
Ray

From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of Yao, Jiewen
Sent: Thursday, September 29, 2016 10:37 AM
To: Kinney, Michael D <michael.d.kinney@intel.com>; edk2-devel@lists.01.org
Cc: Tian, Feng <feng.tian@intel.com>; Zhang, Chao B <chao.b.zhang@intel.com>; Gao, Liming <liming.gao@intel.com>; Zeng, Star <star.zeng@intel.com>
Subject: Re: [edk2] [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application.

Right. CapsuleOnDisk is not supported in BIOS yet.
I will remove it in CapsuleApp.

CapsuleApp just works as an agent to pass capsule to CapsuleDxeRuntime driver.
So it is checked by CapsuleDxeRuntime, not CapsuleApp.

Thank you
Yao Jiewen

From: Kinney, Michael D
Sent: Thursday, September 29, 2016 9:06 AM
To: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>; Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>
Cc: Tian, Feng <feng.tian@intel.com<mailto:feng.tian@intel.com>>; Zeng, Star <star.zeng@intel.com<mailto:star.zeng@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: [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application.

Jiewen,

Does the capsule on disk feature provided by this app work?

I tried it with the QuarkPlatformPkg capsule and I can get
The app to copy the capsule to an EFI System Partition, but
The logic after that point looks incomplete.

Also, if I clear the Persist and Reset flags on the capsule,
the immediate processing of the capsule does not work.

Is there any FW code that will look for capsules on disk?

If there are incomplete features in CapsuleApp, then I think
we should remove them.

Mike

> -----Original Message-----
> From: Yao, Jiewen
> Sent: Tuesday, September 20, 2016 11:45 PM
> To: edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org%3cmailto:edk2-devel@lists.01.org>>
> Cc: Tian, Feng <feng.tian@intel.com<mailto:feng.tian@intel.com<mailto:feng.tian@intel.com%3cmailto:feng.tian@intel.com>>>; Zeng, Star <star.zeng@intel.com<mailto:star.zeng@intel.com<mailto:star.zeng@intel.com%3cmailto:star.zeng@intel.com>>>; Kinney, Michael
> D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com%3cmailto:michael.d.kinney@intel.com>>>; Gao, Liming <liming.gao@intel.com<mailto:liming.gao@intel.com<mailto:liming.gao@intel.com%3cmailto:liming.gao@intel.com>>>; Zhang, Chao B
> <chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com%3cmailto:chao.b.zhang@intel.com>>>
> Subject: [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application.
>
> This CapsuleApp can help perform capsule update in UEFI shell environment.
> It can also dump capsule information, capsule status variable, ESRT and FMP.
>
> Cc: Feng Tian <feng.tian@intel.com<mailto:feng.tian@intel.com<mailto:feng.tian@intel.com%3cmailto:feng.tian@intel.com>>>
> Cc: Star Zeng <star.zeng@intel.com<mailto:star.zeng@intel.com<mailto:star.zeng@intel.com%3cmailto:star.zeng@intel.com>>>
> Cc: Michael D Kinney <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com%3cmailto:michael.d.kinney@intel.com>>>
> Cc: Liming Gao <liming.gao@intel.com<mailto:liming.gao@intel.com<mailto:liming.gao@intel.com%3cmailto:liming.gao@intel.com>>>
> Cc: Chao Zhang <chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com%3cmailto:chao.b.zhang@intel.com>>>
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Jiewen Yao <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com<mailto:jiewen.yao@intel.com%3cmailto:jiewen.yao@intel.com>>>
> ---
>  MdeModulePkg/Application/CapsuleApp/AppSupport.c        |  480 +++++++++
>  MdeModulePkg/Application/CapsuleApp/CapsuleApp.c        | 1047 ++++++++++++++++++++
>  MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf      |   71 ++
>  MdeModulePkg/Application/CapsuleApp/CapsuleApp.uni      |   22 +
>  MdeModulePkg/Application/CapsuleApp/CapsuleAppExtra.uni |   19 +
>  MdeModulePkg/Application/CapsuleApp/CapsuleDump.c       |  840 ++++++++++++++++
>  6 files changed, 2479 insertions(+)
>
> diff --git a/MdeModulePkg/Application/CapsuleApp/AppSupport.c
> b/MdeModulePkg/Application/CapsuleApp/AppSupport.c
> new file mode 100644
> index 0000000..365067d
> --- /dev/null
> +++ b/MdeModulePkg/Application/CapsuleApp/AppSupport.c
> @@ -0,0 +1,480 @@
> +/** @file
> +  A shell application that triggers capsule update process.
> +
> +  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the BSD License
> +  which accompanies this distribution.  The full text of the license may be found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +
> +**/
> +
> +#include <Uefi.h>
> +#include <Library/BaseLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/UefiRuntimeServicesTableLib.h>
> +#include <Library/UefiLib.h>
> +#include <Library/PrintLib.h>
> +#include <Protocol/LoadedImage.h>
> +#include <Protocol/SimpleFileSystem.h>
> +#include <Guid/FileInfo.h>
> +#include <Guid/Gpt.h>
> +
> +#define MAX_ARG_NUM     11
> +
> +UINTN  Argc = 0;
> +CHAR16 *Argv[MAX_ARG_NUM];
> +CHAR16 *ArgBuffer;
> +
> +/**
> +
> +  This function parse application ARG.
> +
> +  @return Status
> +**/
> +EFI_STATUS
> +GetArg (
> +  VOID
> +  )
> +{
> +  UINT8                         *Data;
> +  UINTN                         DataSize;
> +  CHAR16                        *Index;
> +  CHAR16                        *End;
> +  CHAR16                        *DIndex;
> +  EFI_STATUS                    Status;
> +  EFI_LOADED_IMAGE_PROTOCOL     *LoadedImage;
> +
> +  Status = gBS->HandleProtocol (
> +                  gImageHandle,
> +                  &gEfiLoadedImageProtocolGuid,
> +                  (VOID**)&LoadedImage
> +                  );
> +  if (EFI_ERROR(Status)) {
> +    return Status;
> +  }
> +
> +  Data = LoadedImage->LoadOptions;
> +  DataSize = LoadedImage->LoadOptionsSize;
> +
> +  End = (CHAR16*)(UINTN)(Data + DataSize);
> +  Status = gBS->AllocatePool (EfiBootServicesData, DataSize, (VOID **)&ArgBuffer);
> +  ASSERT_EFI_ERROR (Status);
> +  DIndex = ArgBuffer;
> +  Argv[Argc++] = ArgBuffer;
> +  for (Index = (CHAR16*)Data; Index < End; ) {
> +    if (*Index == L' ') {
> +      *DIndex = L'\0';
> +      if (Argc >= MAX_ARG_NUM) {
> +        return EFI_UNSUPPORTED;
> +      }
> +      Argv[Argc++] = (++ DIndex);
> +      while(*Index == L' ') {
> +        Index ++;
> +      }
> +    }
> +    (*(DIndex ++)) = (*(Index ++));
> +  }
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Clear APP ARG.
> +**/
> +VOID
> +CleanArg (
> +  VOID
> +  )
> +{
> +  FreePool (Argv[0]);
> +}
> +
> +/**
> +  Return File System Volume containing this shell application.
> +
> +  @return File System Volume containing this shell application.
> +**/
> +EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *
> +GetMyVol (
> +  VOID
> +  )
> +{
> +  EFI_STATUS                        Status;
> +  EFI_LOADED_IMAGE_PROTOCOL         *LoadedImage;
> +  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Vol;
> +
> +  Status = gBS->HandleProtocol (
> +                  gImageHandle,
> +                  &gEfiLoadedImageProtocolGuid,
> +                  (VOID **)&LoadedImage
> +                  );
> +  ASSERT_EFI_ERROR (Status);
> +
> +  Status = gBS->HandleProtocol (
> +                  LoadedImage->DeviceHandle,
> +                  &gEfiSimpleFileSystemProtocolGuid,
> +                  (VOID **)&Vol
> +                  );
> +  if (!EFI_ERROR (Status)) {
> +    return Vol;
> +  }
> +
> +  return NULL;
> +}
> +
> +/**
> +  Read a file from this volume.
> +
> +  @param Vol             File System Volume
> +  @param FileName        The file to be read.
> +  @param BufferSize      The file buffer size
> +  @param Buffer          The file buffer
> +
> +  @retval EFI_SUCCESS    Read file successfully
> +  @retval EFI_NOT_FOUND  File not found
> +**/
> +EFI_STATUS
> +ReadFileFromVol (
> +  IN  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Vol,
> +  IN  CHAR16                            *FileName,
> +  OUT UINTN                             *BufferSize,
> +  OUT VOID                              **Buffer
> +  )
> +{
> +  EFI_STATUS                        Status;
> +  EFI_FILE_HANDLE                   RootDir;
> +  EFI_FILE_HANDLE                   Handle;
> +  UINTN                             FileInfoSize;
> +  EFI_FILE_INFO                     *FileInfo;
> +  UINTN                             TempBufferSize;
> +  VOID                              *TempBuffer;
> +
> +  //
> +  // Open the root directory
> +  //
> +  Status = Vol->OpenVolume (Vol, &RootDir);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  //
> +  // Open the file
> +  //
> +  Status = RootDir->Open (
> +                      RootDir,
> +                      &Handle,
> +                      FileName,
> +                      EFI_FILE_MODE_READ,
> +                      0
> +                      );
> +  if (EFI_ERROR (Status)) {
> +    RootDir->Close (RootDir);
> +    return Status;
> +  }
> +
> +  RootDir->Close (RootDir);
> +
> +  //
> +  // Get the file information
> +  //
> +  FileInfoSize = sizeof(EFI_FILE_INFO) + 1024;
> +
> +  FileInfo = AllocateZeroPool (FileInfoSize);
> +  if (FileInfo == NULL) {
> +    Handle->Close (Handle);
> +    return Status;
> +  }
> +
> +  Status = Handle->GetInfo (
> +                     Handle,
> +                     &gEfiFileInfoGuid,
> +                     &FileInfoSize,
> +                     FileInfo
> +                     );
> +  if (EFI_ERROR (Status)) {
> +    Handle->Close (Handle);
> +    gBS->FreePool (FileInfo);
> +    return Status;
> +  }
> +
> +  //
> +  // Allocate buffer for the file data. The last CHAR16 is for L'\0'
> +  //
> +  TempBufferSize = (UINTN) FileInfo->FileSize + sizeof(CHAR16);
> +  TempBuffer = AllocateZeroPool (TempBufferSize);
> +  if (TempBuffer == NULL) {
> +    Handle->Close (Handle);
> +    gBS->FreePool (FileInfo);
> +    return Status;
> +  }
> +
> +  gBS->FreePool (FileInfo);
> +
> +  //
> +  // Read the file data to the buffer
> +  //
> +  Status = Handle->Read (
> +                     Handle,
> +                     &TempBufferSize,
> +                     TempBuffer
> +                     );
> +  if (EFI_ERROR (Status)) {
> +    Handle->Close (Handle);
> +    gBS->FreePool (TempBuffer);
> +    return Status;
> +  }
> +
> +  Handle->Close (Handle);
> +
> +  *BufferSize = TempBufferSize;
> +  *Buffer     = TempBuffer;
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Read a file.
> +  If ScanFs is FLASE, it will use this Vol as default Fs.
> +  If ScanFs is TRUE, it will scan all FS and check the file.
> +    If there is only one file match the name, it will be read.
> +    If there is more than one file match the name, it will return Error.
> +
> +  @param ThisVol         File System Volume
> +  @param FileName        The file to be read.
> +  @param BufferSize      The file buffer size
> +  @param Buffer          The file buffer
> +  @param ScanFs          Need Scan all FS
> +
> +  @retval EFI_SUCCESS    Read file successfully
> +  @retval EFI_NOT_FOUND  File not found
> +  @retval EFI_NO_MAPPING There is duplicated files found
> +**/
> +EFI_STATUS
> +ReadFileToBufferEx (
> +  IN OUT EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   **ThisVol,
> +  IN  CHAR16                               *FileName,
> +  OUT UINTN                                *BufferSize,
> +  OUT VOID                                 **Buffer,
> +  IN  BOOLEAN                              ScanFs
> +  )
> +{
> +  EFI_STATUS                        Status;
> +  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Vol;
> +  UINTN                             TempBufferSize;
> +  VOID                              *TempBuffer;
> +  UINTN                             NoHandles;
> +  EFI_HANDLE                        *HandleBuffer;
> +  UINTN                             Index;
> +
> +  //
> +  // Check parameters
> +  //
> +  if ((FileName == NULL) || (Buffer == NULL) || (ThisVol == NULL)) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  //
> +  // not scan fs
> +  //
> +  if (!ScanFs) {
> +    if (*ThisVol == NULL) {
> +      *ThisVol = GetMyVol ();
> +      if (*ThisVol == NULL) {
> +        return EFI_INVALID_PARAMETER;
> +      }
> +    }
> +    //
> +    // Read file directly from Vol
> +    //
> +    return ReadFileFromVol (*ThisVol, FileName, BufferSize, Buffer);
> +  }
> +
> +  //
> +  // need scan fs
> +  //
> +
> +  //
> +  // Get all Vol handle
> +  //
> +  Status = gBS->LocateHandleBuffer (
> +                   ByProtocol,
> +                   &gEfiSimpleFileSystemProtocolGuid,
> +                   NULL,
> +                   &NoHandles,
> +                   &HandleBuffer
> +                   );
> +  if (EFI_ERROR (Status) && (NoHandles == 0)) {
> +    return EFI_NOT_FOUND;
> +  }
> +
> +  //
> +  // Walk through each Vol
> +  //
> +  *ThisVol = NULL;
> +  *BufferSize = 0;
> +  *Buffer     = NULL;
> +  for (Index = 0; Index < NoHandles; Index++) {
> +    Status = gBS->HandleProtocol (
> +                    HandleBuffer[Index],
> +                    &gEfiSimpleFileSystemProtocolGuid,
> +                    (VOID **)&Vol
> +                    );
> +    if (EFI_ERROR(Status)) {
> +      continue;
> +    }
> +
> +    Status = ReadFileFromVol (Vol, FileName, &TempBufferSize, &TempBuffer);
> +    if (!EFI_ERROR (Status)) {
> +      //
> +      // Read file OK, check duplication
> +      //
> +      if (*ThisVol != NULL) {
> +        //
> +        // Find the duplicated file
> +        //
> +        gBS->FreePool (TempBuffer);
> +        gBS->FreePool (*Buffer);
> +        Print (L"Duplicated FileName found!\n");
> +        return EFI_NO_MAPPING;
> +      } else {
> +        //
> +        // Record value
> +        //
> +        *ThisVol = Vol;
> +        *BufferSize = TempBufferSize;
> +        *Buffer     = TempBuffer;
> +      }
> +    }
> +  }
> +
> +  //
> +  // Scan Fs done
> +  //
> +  if (*ThisVol == NULL) {
> +    return EFI_NOT_FOUND;
> +  }
> +
> +  //
> +  // Done
> +  //
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Read a file.
> +
> +  @param FileName        The file to be read.
> +  @param BufferSize      The file buffer size
> +  @param Buffer          The file buffer
> +
> +  @retval EFI_SUCCESS    Read file successfully
> +  @retval EFI_NOT_FOUND  File not found
> +**/
> +EFI_STATUS
> +ReadFileToBuffer (
> +  IN  CHAR16                               *FileName,
> +  OUT UINTN                                *BufferSize,
> +  OUT VOID                                 **Buffer
> +  )
> +{
> +  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Vol;
> +  Vol = NULL;
> +  return ReadFileToBufferEx(&Vol, FileName, BufferSize, Buffer, FALSE);
> +}
> +
> +/**
> +  Write a file.
> +
> +  @param FileName        The file to be written.
> +  @param BufferSize      The file buffer size
> +  @param Buffer          The file buffer
> +
> +  @retval EFI_SUCCESS    Write file successfully
> +**/
> +EFI_STATUS
> +WriteFileFromBuffer(
> +  IN  CHAR16                               *FileName,
> +  IN  UINTN                                BufferSize,
> +  IN  VOID                                 *Buffer
> +  )
> +{
> +  EFI_STATUS                        Status;
> +  EFI_FILE_HANDLE                   RootDir;
> +  EFI_FILE_HANDLE                   Handle;
> +  UINTN                             TempBufferSize;
> +  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Vol;
> +
> +  Vol = GetMyVol();
> +
> +  //
> +  // Open the root directory
> +  //
> +  Status = Vol->OpenVolume (Vol, &RootDir);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  //
> +  // Open the file
> +  //
> +  Status = RootDir->Open (
> +                      RootDir,
> +                      &Handle,
> +                      FileName,
> +                      EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE| EFI_FILE_MODE_CREATE,
> +                      0
> +                      );
> +  if (EFI_ERROR (Status)) {
> +    RootDir->Close (RootDir);
> +    return Status;
> +  }
> +
> +  //
> +  // Delete file
> +  //
> +  Status = Handle->Delete(Handle);
> +  if (EFI_ERROR(Status)) {
> +    return Status;
> +  }
> +
> +  //
> +  // Open the file again
> +  //
> +  Status = RootDir->Open (
> +                      RootDir,
> +                      &Handle,
> +                      FileName,
> +                      EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE| EFI_FILE_MODE_CREATE,
> +                      0
> +                      );
> +  if (EFI_ERROR (Status)) {
> +    RootDir->Close (RootDir);
> +    return Status;
> +  }
> +
> +  RootDir->Close (RootDir);
> +
> +  //
> +  // Write the file data from the buffer
> +  //
> +  TempBufferSize = BufferSize;
> +  Status = Handle->Write (
> +                     Handle,
> +                     &TempBufferSize,
> +                     Buffer
> +                     );
> +  if (EFI_ERROR (Status)) {
> +    Handle->Close (Handle);
> +    return Status;
> +  }
> +
> +  Handle->Close (Handle);
> +
> +  return EFI_SUCCESS;
> +}
> +
> diff --git a/MdeModulePkg/Application/CapsuleApp/CapsuleApp.c
> b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.c
> new file mode 100644
> index 0000000..0a28557
> --- /dev/null
> +++ b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.c
> @@ -0,0 +1,1047 @@
> +/** @file
> +  A shell application that triggers capsule update process.
> +
> +  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the BSD License
> +  which accompanies this distribution.  The full text of the license may be found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +
> +**/
> +
> +#include <Uefi.h>
> +#include <Library/BaseLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/UefiRuntimeServicesTableLib.h>
> +#include <Library/UefiLib.h>
> +#include <Library/PrintLib.h>
> +#include <Protocol/LoadedImage.h>
> +#include <Protocol/SimpleFileSystem.h>
> +#include <Protocol/GraphicsOutput.h>
> +#include <Guid/FileInfo.h>
> +#include <Guid/Gpt.h>
> +#include <Guid/GlobalVariable.h>
> +#include <Guid/CapsuleReport.h>
> +#include <Guid/SystemResourceTable.h>
> +#include <Guid/FmpCapsule.h>
> +#include <IndustryStandard/WindowsUxCapsule.h>
> +
> +#define CAPSULE_HEADER_SIZE  0x20
> +
> +#define NESTED_CAPSULE_HEADER_SIZE  SIZE_4KB
> +#define SYSTEM_FIRMWARE_FLAG 0x50000
> +#define DEVICE_FIRMWARE_FLAG 0x78010
> +
> +#define EFI_CAPSULE_FROM_FILE_DIR                           L"\\EFI\\UpdateCapsule\\<file:///\\EFI\UpdateCapsule\><file://EFI/UpdateCapsule/%3cfile:/EFI/UpdateCapsule/%3e>"
> +#define EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED  0x0000000000000004
> +
> +#define MAJOR_VERSION   1
> +#define MINOR_VERSION   0
> +
> +#define MAX_ARG_NUM     11
> +#define MAX_CAPSULE_NUM (MAX_ARG_NUM - 1)
> +
> +extern UINTN  Argc;
> +extern CHAR16 *Argv[];
> +
> +//
> +// Define how many block descriptors we want to test with.
> +//
> +UINTN  NumberOfDescriptors = 1;
> +UINTN  CapsuleFirstIndex;
> +UINTN  CapsuleLastIndex;
> +
> +/**
> +  Dump capsule information
> +
> +  @retval EFI_SUCCESS            The capsule information is dumped.
> +  @retval EFI_UNSUPPORTED        Input parameter is not valid.
> +**/
> +EFI_STATUS
> +DumpCapsule(
> +  VOID
> +  );
> +
> +/**
> +  Dump capsule status variable.
> +
> +  @retval EFI_SUCCESS            The capsule status variable is dumped.
> +  @retval EFI_UNSUPPORTED        Input parameter is not valid.
> +**/
> +EFI_STATUS
> +DmpCapsuleStatusVariable(
> +  VOID
> +  );
> +
> +/**
> +  Dump FMP protocol info.
> +**/
> +VOID
> +DumpFmpData(
> +  VOID
> +  );
> +
> +/**
> +  Dump ESRT info.
> +**/
> +VOID
> +DumpEsrtData(
> +  VOID
> +  );
> +
> +/**
> +  Read a file.
> +
> +  @param FileName        The file to be read.
> +  @param BufferSize      The file buffer size
> +  @param Buffer          The file buffer
> +
> +  @retval EFI_SUCCESS    Read file successfully
> +  @retval EFI_NOT_FOUND  File not found
> +**/
> +EFI_STATUS
> +ReadFileToBuffer(
> +  IN  CHAR16                               *FileName,
> +  OUT UINTN                                *BufferSize,
> +  OUT VOID                                 **Buffer
> +  );
> +
> +/**
> +  Write a file.
> +
> +  @param FileName        The file to be written.
> +  @param BufferSize      The file buffer size
> +  @param Buffer          The file buffer
> +
> +  @retval EFI_SUCCESS    Write file successfully
> +**/
> +EFI_STATUS
> +WriteFileFromBuffer(
> +  IN  CHAR16                               *FileName,
> +  IN  UINTN                                BufferSize,
> +  IN  VOID                                 *Buffer
> +  );
> +
> +/**
> +
> +  This function parse application ARG.
> +
> +  @return Status
> +**/
> +EFI_STATUS
> +GetArg (
> +  VOID
> +  );
> +
> +/**
> +  Clear APP ARG.
> +**/
> +VOID
> +CleanArg (
> +  VOID
> +  );
> +
> +/**
> +  Create UX capsule.
> +
> +  @retval EFI_SUCCESS            The capsule header is appended.
> +  @retval EFI_UNSUPPORTED        Input parameter is not valid.
> +  @retval EFI_OUT_OF_RESOURCES   No enough resource to create UX capsule.
> +**/
> +EFI_STATUS
> +CreateBmpFmp(
> +  VOID
> +  )
> +{
> +  CHAR16                                        *OutputCapsuleName;
> +  VOID                                          *BmpBuffer;
> +  UINTN                                         FileSize;
> +  CHAR16                                        *BmpName;
> +  UINT8                                         *FullCapsuleBuffer;
> +  UINTN                                         FullCapsuleBufferSize;
> +  EFI_DISPLAY_CAPSULE                           *DisplayCapsule;
> +  EFI_STATUS                                    Status;
> +  EFI_GRAPHICS_OUTPUT_PROTOCOL                  *Gop;
> +
> +  Status = gBS->LocateProtocol(&gEfiGraphicsOutputProtocolGuid, NULL, (VOID **)&Gop);
> +  if (EFI_ERROR(Status)) {
> +    Print(L"CapsuleApp: NO GOP is found.\n");
> +    return EFI_UNSUPPORTED;
> +  }
> +  Print(L"Current GOP: Mode - %d, ", Gop->Mode->Mode);
> +  Print(L"HorizontalResolution - %d, ", Gop->Mode->Info->HorizontalResolution);
> +  Print(L"VerticalResolution - %d\n", Gop->Mode->Info->VerticalResolution);
> +  // HorizontalResolution >= BMP_IMAGE_HEADER.PixelWidth
> +  // VerticalResolution   >= BMP_IMAGE_HEADER.PixelHeight
> +
> +  if (Argc != 5) {
> +    Print(L"CapsuleApp: Invalid Parameter.\n");
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  if (StrCmp(Argv[3], L"-O") != 0) {
> +    Print(L"CapsuleApp: NO output capsule name.\n");
> +    return EFI_UNSUPPORTED;
> +  }
> +  OutputCapsuleName = Argv[4];
> +
> +  BmpBuffer = NULL;
> +  FileSize = 0;
> +  FullCapsuleBuffer = NULL;
> +
> +  BmpName = Argv[2];
> +  Status = ReadFileToBuffer(BmpName, &FileSize, &BmpBuffer);
> +  if (EFI_ERROR(Status)) {
> +    Print(L"CapsuleApp: BMP image (%s) is not found.\n", BmpName);
> +    goto Done;
> +  }
> +
> +  FullCapsuleBufferSize = sizeof(EFI_DISPLAY_CAPSULE) + FileSize;
> +  FullCapsuleBuffer = AllocatePool(FullCapsuleBufferSize);
> +  if (FullCapsuleBuffer == NULL) {
> +    Print(L"CapsuleApp: Capsule Buffer size (0x%x) too big.\n",
> FullCapsuleBufferSize);
> +    Status = EFI_OUT_OF_RESOURCES;
> +    goto Done;
> +  }
> +
> +  DisplayCapsule = (EFI_DISPLAY_CAPSULE *)FullCapsuleBuffer;
> +  CopyGuid(&DisplayCapsule->CapsuleHeader.CapsuleGuid, &gWindowsUxCapsuleGuid);
> +  DisplayCapsule->CapsuleHeader.HeaderSize = sizeof(DisplayCapsule->CapsuleHeader);
> +  DisplayCapsule->CapsuleHeader.Flags = CAPSULE_FLAGS_PERSIST_ACROSS_RESET;
> +  DisplayCapsule->CapsuleHeader.CapsuleImageSize = (UINT32)FullCapsuleBufferSize;
> +
> +  DisplayCapsule->ImagePayload.Version = 1;
> +  DisplayCapsule->ImagePayload.Checksum = 0;
> +  DisplayCapsule->ImagePayload.ImageType = 0; // BMP
> +  DisplayCapsule->ImagePayload.Reserved = 0;
> +  DisplayCapsule->ImagePayload.Mode = Gop->Mode->Mode;
> +  DisplayCapsule->ImagePayload.OffsetX = 0;
> +  DisplayCapsule->ImagePayload.OffsetY = 0;
> +
> +  CopyMem((DisplayCapsule + 1), BmpBuffer, FileSize);
> +
> +  DisplayCapsule->ImagePayload.Checksum = CalculateCheckSum8(FullCapsuleBuffer,
> FullCapsuleBufferSize);
> +
> +  Status = WriteFileFromBuffer(OutputCapsuleName, FullCapsuleBufferSize,
> FullCapsuleBuffer);
> +  Print(L"CapsuleApp: Write %s %r\n", OutputCapsuleName, Status);
> +
> +Done:
> +  if (BmpBuffer != NULL) {
> +    FreePool(BmpBuffer);
> +  }
> +
> +  if (FullCapsuleBuffer != NULL) {
> +    FreePool(FullCapsuleBuffer);
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  Get ImageTypeId in the FMP capsule header.
> +
> +  @param CapsuleHeader  The FMP capsule image header.
> +
> +  @return ImageTypeId
> +**/
> +EFI_GUID *
> +GetCapsuleImageTypeId(
> +  IN EFI_CAPSULE_HEADER                            *CapsuleHeader
> +  )
> +{
> +  EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER       *FmpCapsuleHeader;
> +  UINT64                                       *ItemOffsetList;
> +  EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader;
> +
> +  FmpCapsuleHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *)((UINT8 *)CapsuleHeader
> + CapsuleHeader->HeaderSize);
> +  ItemOffsetList = (UINT64 *)(FmpCapsuleHeader + 1);
> +  if (FmpCapsuleHeader->PayloadItemCount == 0) {
> +    return NULL;
> +  }
> +  ImageHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *)((UINT8
> *)FmpCapsuleHeader + ItemOffsetList[FmpCapsuleHeader->EmbeddedDriverCount]);
> +  return &ImageHeader->UpdateImageTypeId;
> +}
> +
> +/**
> +  Get ESRT FwType according to ImageTypeId
> +
> +  @param  ImageTypeId   ImageTypeId of an FMP capsule.
> +
> +  @return ESRT FwType
> +**/
> +UINT32
> +GetEsrtFwType(
> +  IN  EFI_GUID                                      *ImageTypeId
> +  )
> +{
> +  EFI_STATUS                 Status;
> +  EFI_SYSTEM_RESOURCE_TABLE  *Esrt;
> +  EFI_SYSTEM_RESOURCE_ENTRY  *EsrtEntry;
> +  UINTN                      Index;
> +
> +  //
> +  // Check ESRT
> +  //
> +  Status = EfiGetSystemConfigurationTable(&gEfiSystemResourceTableGuid, (VOID
> **)&Esrt);
> +  if (!EFI_ERROR(Status)) {
> +    EsrtEntry = (VOID *)(Esrt + 1);
> +    for (Index = 0; Index < Esrt->FwResourceCount; Index++, EsrtEntry++) {
> +      if (CompareGuid(&EsrtEntry->FwClass, ImageTypeId)) {
> +        return EsrtEntry->FwType;
> +      }
> +    }
> +  }
> +
> +  return ESRT_FW_TYPE_UNKNOWN;
> +}
> +
> +/**
> +  Append a capsule header on top of current image.
> +  This function follows Windows UEFI Firmware Update Platform document.
> +
> +  @retval EFI_SUCCESS            The capsule header is appended.
> +  @retval EFI_UNSUPPORTED        Input parameter is not valid.
> +  @retval EFI_OUT_OF_RESOURCES   No enough resource to append capsule header.
> +**/
> +EFI_STATUS
> +CreateNestedFmp(
> +  VOID
> +  )
> +{
> +  CHAR16                                        *OutputCapsuleName;
> +  VOID                                          *CapsuleBuffer;
> +  UINTN                                         FileSize;
> +  CHAR16                                        *CapsuleName;
> +  UINT8                                         *FullCapsuleBuffer;
> +  UINTN                                         FullCapsuleBufferSize;
> +  EFI_CAPSULE_HEADER                            *NestedCapsuleHeader;
> +  EFI_GUID                                      *ImageTypeId;
> +  UINT32                                        FwType;
> +  EFI_STATUS                                    Status;
> +
> +  if (Argc != 5) {
> +    Print(L"CapsuleApp: Invalid Parameter.\n");
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  if (StrCmp(Argv[3], L"-O") != 0) {
> +    Print(L"CapsuleApp: NO output capsule name.\n");
> +    return EFI_UNSUPPORTED;
> +  }
> +  OutputCapsuleName = Argv[4];
> +
> +  CapsuleBuffer = NULL;
> +  FileSize = 0;
> +  FullCapsuleBuffer = NULL;
> +
> +  CapsuleName = Argv[2];
> +  Status = ReadFileToBuffer(CapsuleName, &FileSize, &CapsuleBuffer);
> +  if (EFI_ERROR(Status)) {
> +    Print(L"CapsuleApp: Capsule image (%s) is not found.\n", CapsuleName);
> +    goto Done;
> +  }
> +
> +  ImageTypeId = GetCapsuleImageTypeId(CapsuleBuffer);
> +  if (ImageTypeId == NULL) {
> +    Print(L"CapsuleApp: Capsule ImageTypeId is not found.\n");
> +    goto Done;
> +  }
> +  FwType = GetEsrtFwType(ImageTypeId);
> +  if ((FwType != ESRT_FW_TYPE_SYSTEMFIRMWARE) && (FwType !=
> ESRT_FW_TYPE_DEVICEFIRMWARE)) {
> +    Print(L"CapsuleApp: Capsule FwType is invalid.\n");
> +    goto Done;
> +  }
> +
> +  FullCapsuleBufferSize = NESTED_CAPSULE_HEADER_SIZE + FileSize;
> +  FullCapsuleBuffer = AllocatePool(FullCapsuleBufferSize);
> +  if (FullCapsuleBuffer == NULL) {
> +    Print(L"CapsuleApp: Capsule Buffer size (0x%x) too big.\n",
> FullCapsuleBufferSize);
> +    Status = EFI_OUT_OF_RESOURCES;
> +    goto Done;
> +  }
> +
> +  NestedCapsuleHeader = (EFI_CAPSULE_HEADER *)FullCapsuleBuffer;
> +  ZeroMem(NestedCapsuleHeader, NESTED_CAPSULE_HEADER_SIZE);
> +  CopyGuid(&NestedCapsuleHeader->CapsuleGuid, ImageTypeId);
> +  NestedCapsuleHeader->HeaderSize = NESTED_CAPSULE_HEADER_SIZE;
> +  NestedCapsuleHeader->Flags = (FwType == ESRT_FW_TYPE_DEVICEFIRMWARE) ?
> SYSTEM_FIRMWARE_FLAG : DEVICE_FIRMWARE_FLAG;
> +  NestedCapsuleHeader->CapsuleImageSize = (UINT32)FullCapsuleBufferSize;
> +
> +  CopyMem((UINT8 *)NestedCapsuleHeader + NestedCapsuleHeader->HeaderSize,
> CapsuleBuffer, FileSize);
> +
> +  Status = WriteFileFromBuffer(OutputCapsuleName, FullCapsuleBufferSize,
> FullCapsuleBuffer);
> +  Print(L"CapsuleApp: Write %s %r\n", OutputCapsuleName, Status);
> +
> +Done:
> +  if (CapsuleBuffer != NULL) {
> +    FreePool(CapsuleBuffer);
> +  }
> +
> +  if (FullCapsuleBuffer != NULL) {
> +    FreePool(FullCapsuleBuffer);
> +  }
> +
> +  return Status;
> +}
> +
> +
> +/**
> +  Clear capsule status variable.
> +
> +  @retval EFI_SUCCESS            The capsule status variable is cleared.
> +**/
> +EFI_STATUS
> +ClearCapsuleStatusVariable(
> +  VOID
> +  )
> +{
> +  EFI_STATUS                          Status;
> +  UINT32                              Index;
> +  CHAR16                              CapsuleVarName[20];
> +  CHAR16                              *TempVarName;
> +
> +  StrCpyS (CapsuleVarName, sizeof(CapsuleVarName)/sizeof(CapsuleVarName[0]),
> L"Capsule");
> +  TempVarName = CapsuleVarName + StrLen (CapsuleVarName);
> +  Index = 0;
> +
> +  while (TRUE) {
> +    UnicodeSPrint (TempVarName, 5 * sizeof(CHAR16), L"%04x", Index);
> +
> +    Status = gRT->SetVariable (
> +                    CapsuleVarName,
> +                    &gEfiCapsuleReportGuid,
> +                    EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS |
> EFI_VARIABLE_BOOTSERVICE_ACCESS,
> +                    0,
> +                    (VOID *)NULL
> +                    );
> +    if (EFI_ERROR(Status)) {
> +      //
> +      // There is no capsule variables, quit
> +      //
> +      break;
> +    }
> +
> +    Index++;
> +    if (Index > 0xFFFF) {
> +      break;
> +    }
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Get the active UEFI system partition from bootoption list.
> +
> +  @param[out] Fs    Simple File System protocol on the active UEFI system partition
> +
> +  @retval EFI_SUCCESS   active UEFI system partition found
> +**/
> +EFI_STATUS
> +GetEfiSysPartition(
> +  OUT EFI_SIMPLE_FILE_SYSTEM_PROTOCOL **Fs
> +  )
> +{
> +  EFI_STATUS                       Status;
> +  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL  *FsTemp;
> +  UINTN                            NoHandles;
> +  EFI_HANDLE                       *Handles;
> +  UINTN                            Index;
> +
> +  Handles = NULL;
> +
> +  //
> +  // search for EFI system partition protocol on Boot option device path
> +  //
> +  Status = gBS->LocateHandleBuffer(ByProtocol, &gEfiPartTypeSystemPartGuid, NULL,
> &NoHandles, &Handles);
> +  if (EFI_ERROR(Status)) {
> +    return Status;
> +  }
> +
> +  //
> +  // Skip BootOptions within FV
> +  //
> +  for (Index = 0; Index < NoHandles; Index++) {
> +    Status = gBS->HandleProtocol (Handles[Index], &gEfiSimpleFileSystemProtocolGuid,
> (VOID **)&FsTemp);
> +    if (!EFI_ERROR (Status)){
> +      *Fs = FsTemp;
> +      break;
> +    }
> +  }
> +  return Status;
> +}
> +
> +/**
> +  Copy a list of capsule images to the active UEFI system partition from bootoption
> list.
> +
> +  @param[in] CapsuleBuffer    An array of pointer to capsule images
> +  @param[in] FileSize         An array of UINTN to capsule images size
> +  @param[in] CapsuleNum       The count of capsule images
> +
> +  @retval EFI_SUCCESS   Capsule images are copied to the active UEFI system partition
> +**/
> +EFI_STATUS
> +CopyCapsuleToActiveEfiPartition(
> +  IN VOID                          **CapsuleBuffer,
> +  IN UINTN                         *FileSize,
> +  IN UINTN                         CapsuleNum
> +  )
> +{
> +  EFI_STATUS                       Status;
> +  CHAR16                           *CapsuleName;
> +  UINTN                            Index;
> +  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL  *Fs;
> +  EFI_FILE_HANDLE                  RootDir;
> +  EFI_FILE_HANDLE                  CapsuleDir;
> +  EFI_FILE_HANDLE                  DestHandle;
> +  UINTN                            DataSize;
> +  UINT64                           OsIndication;
> +
> +  RootDir      = NULL;
> +  CapsuleDir   = NULL;
> +
> +  Status = GetEfiSysPartition(&Fs);
> +  if (EFI_ERROR(Status)) {
> +    Print (L"Can not find active UEFI System Partition\n");
> +    return Status;
> +  }
> +
> +  Status = Fs->OpenVolume(Fs, &RootDir);
> +  if (EFI_ERROR(Status)) {
> +    goto EXIT;
> +  }
> +
> +  Status = RootDir->Open(
> +                      RootDir,
> +                      &CapsuleDir,
> +                      EFI_CAPSULE_FROM_FILE_DIR,
> +                      EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE,
> +                      EFI_FILE_DIRECTORY
> +                      );
> +  if (EFI_ERROR(Status)) {
> +    goto EXIT;
> +  }
> +
> +  //
> +  // Read the input files.
> +  //
> +  for (Index = 0; Index < CapsuleNum; Index++) {
> +    CapsuleName = Argv[CapsuleFirstIndex + Index];
> +    Status = CapsuleDir->Open(
> +                           CapsuleDir,
> +                           &DestHandle,
> +                           CapsuleName,
> +                           EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE |
> EFI_FILE_MODE_CREATE,
> +                           EFI_FILE_ARCHIVE
> +                           );
> +    if (EFI_ERROR(Status)) {
> +      Print(L"CapsuleApp: %s open error - %r\n", CapsuleName, Status);
> +      continue;
> +    }
> +
> +    DataSize = FileSize[Index];
> +    Status = DestHandle->Write(
> +                           DestHandle,
> +                           &DataSize,
> +                           CapsuleBuffer[Index]
> +                           );
> +    DestHandle->Close(DestHandle);
> +    if (EFI_ERROR(Status)) {
> +      Print(L"CapsuleApp: %s write error - %r, FileSize - 0x%x\n", CapsuleName,
> Status, FileSize[Index]);
> +    }
> +  }
> +
> +  Status = gRT->GetVariable (
> +                  L"OsIndications",
> +                  &gEfiGlobalVariableGuid,
> +                  NULL,
> +                  &DataSize,
> +                  (VOID *) &OsIndication
> +                  );
> +
> +  if (EFI_ERROR(Status) || DataSize != sizeof(OsIndication)) {
> +    OsIndication = 0;
> +  }
> +
> +  //
> +  // Set OsIndications Variable EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED bit
> +  //
> +  OsIndication |= EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED;
> +  Status = gRT->SetVariable (
> +                  L"OsIndications",
> +                  &gEfiGlobalVariableGuid,
> +                  EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS |
> +                  EFI_VARIABLE_BOOTSERVICE_ACCESS,
> +                  sizeof(OsIndication),
> +                  (VOID *)&OsIndication
> +                  );
> +
> +
> +EXIT:
> +  if (RootDir != NULL) {
> +    RootDir->Close(RootDir);
> +  }
> +
> +  if (CapsuleDir != NULL) {
> +    CapsuleDir->Close(CapsuleDir);
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  Build Gather list for a list of capsule images.
> +
> +  @param[in]  CapsuleBuffer    An array of pointer to capsule images
> +  @param[in]  FileSize         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                         *FileSize,
> +  IN UINTN                         CapsuleNum,
> +  OUT EFI_CAPSULE_BLOCK_DESCRIPTOR **BlockDescriptors
> +  )
> +{
> +  EFI_STATUS                    Status;
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR  *BlockDescriptors1;
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR  *BlockDescriptors2;
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR  *BlockDescriptorPre;
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR  *BlockDescriptorsHeader;
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR  *TempBlockPtr;
> +  UINT8                         *TempDataPtr;
> +  UINTN                         SizeLeft;
> +  UINTN                         Size;
> +  INT32                         Count;
> +  INT32                         Number;
> +  UINTN                         Index;
> +
> +  TempBlockPtr           = NULL;
> +  BlockDescriptors1      = NULL;
> +  BlockDescriptors2      = NULL;
> +  BlockDescriptorPre     = NULL;
> +  BlockDescriptorsHeader = NULL;
> +
> +  for (Index = 0; Index < CapsuleNum; Index++) {
> +    //
> +    // Allocate memory for the descriptors.
> +    //
> +    if (NumberOfDescriptors == 1) {
> +      Count = 2;
> +    } else {
> +      Count = (INT32)(NumberOfDescriptors + 2) / 2;
> +    }
> +
> +    Size               = Count * sizeof (EFI_CAPSULE_BLOCK_DESCRIPTOR);
> +    BlockDescriptors1  = AllocateRuntimeZeroPool (Size);
> +    if (BlockDescriptors1 == NULL) {
> +      Print (L"CapsuleApp: failed to allocate memory for descriptors\n");
> +      Status = EFI_OUT_OF_RESOURCES;
> +      goto ERREXIT;
> +    } else {
> +      Print (L"CapsuleApp: creating capsule descriptors at 0x%X\n", (UINTN)
> BlockDescriptors1);
> +      Print (L"CapsuleApp: capsule data starts          at 0x%X with size 0x%X\n",
> (UINTN) CapsuleBuffer, FileSize);
> +    }
> +
> +    //
> +    // Record descirptor header
> +    //
> +    if (Index == 0) {
> +      BlockDescriptorsHeader = BlockDescriptors1;
> +    }
> +
> +    if (BlockDescriptorPre != NULL) {
> +      BlockDescriptorPre->Union.ContinuationPointer = (UINTN) BlockDescriptors1;
> +      BlockDescriptorPre->Length = 0;
> +    }
> +
> +    //
> +    // Fill them in
> +    //
> +    TempBlockPtr  = BlockDescriptors1;
> +    TempDataPtr   = CapsuleBuffer[Index];
> +    SizeLeft      = FileSize[Index];
> +    for (Number = 0; (Number < Count - 1) && (SizeLeft != 0); Number++) {
> +      //
> +      // Divide remaining data in half
> +      //
> +      if (NumberOfDescriptors != 1) {
> +        if (SizeLeft == 1) {
> +          Size = 1;
> +        } else {
> +          Size = SizeLeft / 2;
> +        }
> +      } else {
> +        Size = SizeLeft;
> +      }
> +      TempBlockPtr->Union.DataBlock    = (UINTN)TempDataPtr;
> +      TempBlockPtr->Length  = Size;
> +      Print (L"CapsuleApp: capsule block/size              0x%X/0x%X\n", (UINTN)
> TempDataPtr, Size);
> +      SizeLeft -= Size;
> +      TempDataPtr += Size;
> +      TempBlockPtr++;
> +    }
> +
> +    //
> +    // Allocate the second list, point the first block's last entry to point
> +    // to this one, and fill this one in. Worst case is that the previous
> +    // list only had one element that pointed here, so we need at least two
> +    // elements -- one to point to all the data, another to terminate the list.
> +    //
> +    if ((NumberOfDescriptors != 1) && (SizeLeft != 0)) {
> +      Count = (INT32)(NumberOfDescriptors + 2) - Count;
> +      if (Count == 1) {
> +        Count++;
> +      }
> +
> +      Size              = Count * sizeof (EFI_CAPSULE_BLOCK_DESCRIPTOR);
> +      BlockDescriptors2 = AllocateRuntimeZeroPool (Size);
> +      if (BlockDescriptors2 == NULL) {
> +        Print (L"CapsuleApp: failed to allocate memory for descriptors\n");
> +        Status = EFI_OUT_OF_RESOURCES;
> +        goto ERREXIT;
> +      }
> +
> +      //
> +      // Point the first list's last element to point to this second list.
> +      //
> +      TempBlockPtr->Union.ContinuationPointer   = (UINTN) BlockDescriptors2;
> +
> +      TempBlockPtr->Length  = 0;
> +      TempBlockPtr = BlockDescriptors2;
> +      for (Number = 0; Number < Count - 1; Number++) {
> +        //
> +        // If second-to-last one, then dump rest to this element
> +        //
> +        if (Number == (Count - 2)) {
> +          Size = SizeLeft;
> +        } else {
> +          //
> +          // Divide remaining data in half
> +          //
> +          if (SizeLeft == 1) {
> +            Size = 1;
> +          } else {
> +            Size = SizeLeft / 2;
> +          }
> +        }
> +
> +        TempBlockPtr->Union.DataBlock    = (UINTN)TempDataPtr;
> +        TempBlockPtr->Length  = Size;
> +        Print (L"CapsuleApp: capsule block/size              0x%X/0x%X\n", (UINTN)
> TempDataPtr, Size);
> +        SizeLeft -= Size;
> +        TempDataPtr += Size;
> +        TempBlockPtr++;
> +        if (SizeLeft == 0) {
> +          break;
> +        }
> +      }
> +    }
> +
> +    BlockDescriptorPre = TempBlockPtr;
> +    BlockDescriptors1  = NULL;
> +  }
> +
> +  //
> +  // Null-terminate.
> +  //
> +  if (TempBlockPtr != NULL) {
> +    TempBlockPtr->Union.ContinuationPointer    = (UINTN)NULL;
> +    TempBlockPtr->Length  = 0;
> +    *BlockDescriptors = BlockDescriptorsHeader;
> +  }
> +
> +  return EFI_SUCCESS;
> +
> +ERREXIT:
> +  if (BlockDescriptors1 != NULL) {
> +    FreePool(BlockDescriptors1);
> +  }
> +
> +  if (BlockDescriptors2 != NULL) {
> +    FreePool(BlockDescriptors2);
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  Clear the Gather list for a list of capsule images.
> +
> +  @param[in]  BlockDescriptors The block descriptors for the capsule images
> +  @param[in]  CapsuleNum       The count of capsule images
> +**/
> +VOID
> +CleanGatherList(
> +  IN EFI_CAPSULE_BLOCK_DESCRIPTOR   *BlockDescriptors,
> +  IN UINTN                          CapsuleNum
> +  )
> +{
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR   *TempBlockPtr;
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR   *TempBlockPtr1;
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR   *TempBlockPtr2;
> +  UINTN                          Index;
> +
> +  if (BlockDescriptors != NULL) {
> +    TempBlockPtr1 = BlockDescriptors;
> +    while (1){
> +      TempBlockPtr = TempBlockPtr1;
> +      for (Index = 0; Index < CapsuleNum; Index++) {
> +        if (TempBlockPtr[Index].Length == 0) {
> +          break;
> +        }
> +      }
> +
> +      if (TempBlockPtr[Index].Union.ContinuationPointer == (UINTN)NULL) {
> +        break;
> +      }
> +
> +      TempBlockPtr2 = (VOID *) ((UINTN) TempBlockPtr->Union.ContinuationPointer);
> +      FreePool(TempBlockPtr1);
> +      TempBlockPtr1 = TempBlockPtr2;
> +    }
> +  }
> +}
> +
> +/**
> +  Print APP usage.
> +**/
> +VOID
> +PrintUsage (
> +  VOID
> +  )
> +{
> +  Print(L"CapsuleApp:  usage\n");
> +  Print(L"  CapsuleApp [-F] <Capsule...> [-NR]\n");
> +  Print(L"  CapsuleApp -S\n");
> +  Print(L"  CapsuleApp -C\n");
> +  Print(L"  CapsuleApp -P\n");
> +  Print(L"  CapsuleApp -E\n");
> +  Print(L"  CapsuleApp -G <BMP> -O <Capsule>\n");
> +  Print(L"  CapsuleApp -N <Capsule> -O <NestedCapsule>\n");
> +  Print(L"  CapsuleApp -D|-DS <Capsule>\n");
> +  Print(L"Parameter:\n");
> +  Print(L"  -F:  Put capsule file to disk.\n");
> +  Print(L"       No -F means to put capsule file in memory.\n");
> +  Print(L"  -NR: No Reset.\n");
> +  Print(L"  -S:  Dump capsule status.\n");
> +  Print(L"  -C:  Clear capsule status.\n");
> +  Print(L"  -P:  Dump FMP protocol info.\n");
> +  Print(L"  -E:  Dump ESRT table info.\n");
> +  Print(L"  -G:  Input BMP file name\n");
> +  Print(L"  -N:  Append Capsule Header accroding to Windows Firmware Update\n");
> +  Print(L"  -O:  Output Capsule file name\n");
> +  Print(L"  -D:  Dump Capsule\n");
> +  Print(L"  -DS: Dump Capsule with System FMP format\n");
> +}
> +
> +/**
> +  Update Capsule image.
> +
> +  @param[in]  ImageHandle     The image handle.
> +  @param[in]  SystemTable     The system table.
> +
> +  @retval EFI_SUCCESS            Command completed successfully.
> +  @retval EFI_INVALID_PARAMETER  Command usage error.
> +  @retval EFI_NOT_FOUND          The input file can't be found.
> +**/
> +EFI_STATUS
> +EFIAPI
> +UefiMain (
> +  IN EFI_HANDLE        ImageHandle,
> +  IN EFI_SYSTEM_TABLE  *SystemTable
> +  )
> +{
> +  EFI_STATUS                    Status;
> +  UINTN                         FileSize[MAX_CAPSULE_NUM];
> +  VOID                          *CapsuleBuffer[MAX_CAPSULE_NUM];
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR  *BlockDescriptors;
> +  EFI_CAPSULE_HEADER             *CapsuleHeaderArray[MAX_CAPSULE_NUM + 1];
> +  UINT64                         MaxCapsuleSize;
> +  EFI_RESET_TYPE                 ResetType;
> +  BOOLEAN                        NeedReset;
> +  BOOLEAN                        NoReset;
> +  BOOLEAN                        NeedCopyOnDisk;
> +  CHAR16                         *CapsuleName;
> +  UINTN                          CapsuleNum;
> +  UINTN                          Index;
> +
> +  Status = GetArg();
> +  if (EFI_ERROR(Status)) {
> +    PrintUsage();
> +    return Status;
> +  }
> +  if (Argc < 2) {
> +    PrintUsage();
> +    CleanArg();
> +    return EFI_INVALID_PARAMETER;
> +  }
> +  if ((StrCmp(Argv[1], L"-D") == 0) ||
> +      (StrCmp(Argv[1], L"-DS") == 0)) {
> +    Status = DumpCapsule();
> +    CleanArg();
> +    return Status;
> +  }
> +  if (StrCmp(Argv[1], L"-G") == 0) {
> +    Status = CreateBmpFmp();
> +    CleanArg();
> +    return Status;
> +  }
> +  if (StrCmp(Argv[1], L"-N") == 0) {
> +    Status = CreateNestedFmp();
> +    CleanArg();
> +    return Status;
> +  }
> +  if (StrCmp(Argv[1], L"-S") == 0) {
> +    Status = DmpCapsuleStatusVariable();
> +    CleanArg();
> +    return EFI_SUCCESS;
> +  }
> +  if (StrCmp(Argv[1], L"-C") == 0) {
> +    Status = ClearCapsuleStatusVariable();
> +    CleanArg();
> +    return Status;
> +  }
> +  if (StrCmp(Argv[1], L"-P") == 0) {
> +    DumpFmpData();
> +    CleanArg();
> +    return EFI_SUCCESS;
> +  }
> +  if (StrCmp(Argv[1], L"-E") == 0) {
> +    DumpEsrtData();
> +    CleanArg();
> +    return EFI_SUCCESS;
> +  }
> +  if (StrCmp(Argv[1], L"-F") == 0) {
> +    NeedCopyOnDisk = TRUE;
> +    CapsuleFirstIndex = 2;
> +  } else {
> +    NeedCopyOnDisk = FALSE;
> +    CapsuleFirstIndex = 1;
> +  }
> +  if (StrCmp(Argv[Argc - 1], L"-NR") == 0) {
> +    NoReset = TRUE;
> +    CapsuleLastIndex = Argc - 2;
> +  } else {
> +    NoReset = FALSE;
> +    CapsuleLastIndex = Argc - 1;
> +  }
> +  CapsuleNum = CapsuleLastIndex - CapsuleFirstIndex + 1;
> +
> +  if (CapsuleFirstIndex > CapsuleLastIndex) {
> +    Print(L"CapsuleApp: NO capsule image.\n");
> +    CleanArg();
> +    return EFI_UNSUPPORTED;
> +  }
> +  if (CapsuleNum > MAX_CAPSULE_NUM) {
> +    Print(L"CapsuleApp: Too many capsule images.\n");
> +    CleanArg();
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  ZeroMem(&CapsuleBuffer, sizeof(CapsuleBuffer));
> +  ZeroMem(&FileSize, sizeof(FileSize));
> +  BlockDescriptors = NULL;
> +
> +  for (Index = 0; Index < CapsuleNum; Index++) {
> +    CapsuleName = Argv[CapsuleFirstIndex + Index];
> +    Status = ReadFileToBuffer(CapsuleName, &FileSize[Index], &CapsuleBuffer[Index]);
> +    if (EFI_ERROR(Status)) {
> +      Print(L"CapsuleApp: capsule image (%s) is not found.\n", CapsuleName);
> +      goto Done;
> +    }
> +  }
> +
> +  if (NeedCopyOnDisk) {
> +    Status = CopyCapsuleToActiveEfiPartition(CapsuleBuffer, FileSize, CapsuleNum);
> +  } else {
> +    //
> +    // Every capsule use 2 descriptor 1 for data 1 for end
> +    //
> +    Status = BuildGatherList(CapsuleBuffer, FileSize, CapsuleNum, &BlockDescriptors);
> +  }
> +  if (EFI_ERROR(Status)) {
> +    goto Done;
> +  }
> +
> +  //
> +  // Call the runtime service capsule.
> +  //
> +  NeedReset = FALSE;
> +  for (Index = 0; Index < CapsuleNum; Index++) {
> +    CapsuleHeaderArray[Index] = (EFI_CAPSULE_HEADER *) CapsuleBuffer[Index];
> +    if ((CapsuleHeaderArray[Index]->Flags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET) != 0)
> {
> +      NeedReset = TRUE;
> +    }
> +  }
> +  CapsuleHeaderArray[CapsuleNum] = NULL;
> +  if (NoReset) {
> +    NeedReset = FALSE;
> +  }
> +
> +  //
> +  // Inquire platform capability of UpdateCapsule.
> +  //
> +  Status = gRT->QueryCapsuleCapabilities (CapsuleHeaderArray, CapsuleNum,
> &MaxCapsuleSize, &ResetType);
> +  if (EFI_ERROR(Status)) {
> +    Print (L"CapsuleApp: failed to query capsule capability - %r\n", Status);
> +    goto Done;
> +  }
> +
> +  for (Index = 0; Index < CapsuleNum; Index++) {
> +    if (FileSize[Index] > MaxCapsuleSize) {
> +      Print (L"CapsuleApp: capsule is too large to update, %ld is allowed\n",
> MaxCapsuleSize);
> +      Status = EFI_UNSUPPORTED;
> +      goto Done;
> +    }
> +  }
> +
> +  //
> +  // Check whether the input capsule image has the flag of persist across system
> reset.
> +  //
> +  if (NeedReset) {
> +    Status = gRT->UpdateCapsule(CapsuleHeaderArray,CapsuleNum,(UINTN)
> BlockDescriptors);
> +    if (Status != EFI_SUCCESS) {
> +      Print (L"CapsuleApp: failed to update capsule - %r\n", Status);
> +      goto Done;
> +    }
> +    //
> +    // For capsule who has reset flag, after calling UpdateCapsule service,triger a
> +    // system reset to process capsule persist across a system reset.
> +    //
> +    gRT->ResetSystem (ResetType, EFI_SUCCESS, 0, NULL);
> +  } else {
> +    //
> +    // For capsule who has no reset flag, only call UpdateCapsule Service without a
> +    // system reset. The service will process the capsule immediately.
> +    //
> +    Status = gRT->UpdateCapsule (CapsuleHeaderArray,CapsuleNum,(UINTN)
> BlockDescriptors);
> +    if (Status != EFI_SUCCESS) {
> +      Print (L"CapsuleApp: failed to update capsule - %r\n", Status);
> +    }
> +  }
> +
> +  Status = EFI_SUCCESS;
> +
> +Done:
> +  for (Index = 0; Index < CapsuleNum; Index++) {
> +    if (CapsuleBuffer[Index] != NULL) {
> +      FreePool (CapsuleBuffer[Index]);
> +    }
> +  }
> +
> +  CleanGatherList(BlockDescriptors, CapsuleNum);
> +  CleanArg();
> +
> +  return Status;
> +}
> diff --git a/MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf
> b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf
> new file mode 100644
> index 0000000..7ee44fc
> --- /dev/null
> +++ b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf
> @@ -0,0 +1,71 @@
> +##  @file
> +#  A shell application that triggers capsule update process.
> +#
> +# This application can trigger capsule update process. It can also
> +# generate capsule image, or dump capsule variable information.
> +#
> +#  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
> +#  This program and the accompanying materials
> +#  are licensed and made available under the terms and conditions of the BSD License
> +#  which accompanies this distribution.  The full text of the license may be found at
> +#  http://opensource.org/licenses/bsd-license.php
> +#
> +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +#
> +##
> +
> +[Defines]
> +  INF_VERSION                    = 0x00010006
> +  BASE_NAME                      = CapsuleApp
> +  MODULE_UNI_FILE                = CapsuleApp.uni
> +  FILE_GUID                      = 4CEF31DA-8682-4274-9CC4-AEE7516A5E7B
> +  MODULE_TYPE                    = UEFI_APPLICATION
> +  VERSION_STRING                 = 1.0
> +  ENTRY_POINT                    = UefiMain
> +
> +#
> +# The following information is for reference only and not required by the build tools.
> +#
> +#  VALID_ARCHITECTURES           = IA32 X64
> +#
> +
> +[Sources]
> +  CapsuleApp.c
> +  CapsuleDump.c
> +  AppSupport.c
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +
> +[Guids]
> +  gEfiFileInfoGuid
> +  gEfiPartTypeSystemPartGuid
> +  gEfiGlobalVariableGuid
> +  gEfiCapsuleReportGuid
> +  gEfiFmpCapsuleGuid
> +  gWindowsUxCapsuleGuid
> +  gEfiCertTypeRsa2048Sha256Guid
> +  gEfiCertPkcs7Guid
> +  gEfiSystemResourceTableGuid
> +
> +[Protocols]
> +  gEfiLoadedImageProtocolGuid
> +  gEfiSimpleFileSystemProtocolGuid
> +  gEfiGraphicsOutputProtocolGuid
> +  gEfiFirmwareManagementProtocolGuid
> +
> +[LibraryClasses]
> +  BaseLib
> +  UefiApplicationEntryPoint
> +  DebugLib
> +  MemoryAllocationLib
> +  UefiBootServicesTableLib
> +  UefiRuntimeServicesTableLib
> +  UefiLib
> +  PrintLib
> +  EdkiiSystemCapsuleLib
> +
> +[UserExtensions.TianoCore."ExtraFiles"]
> +  CapsuleAppExtra.uni
> diff --git a/MdeModulePkg/Application/CapsuleApp/CapsuleApp.uni
> b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.uni
> new file mode 100644
> index 0000000..54d6e12
> --- /dev/null
> +++ b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.uni
> @@ -0,0 +1,22 @@
> +// /** @file
> +// A shell application that triggers capsule update process.
> +//
> +// This application can trigger capsule update process. It can also
> +// generate capsule image, or dump capsule variable information.
> +//
> +// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
> +//
> +// This program and the accompanying materials
> +// are licensed and made available under the terms and conditions of the BSD License
> +// which accompanies this distribution. The full text of the license may be found at
> +// http://opensource.org/licenses/bsd-license.php
> +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +//
> +// **/
> +
> +
> +#string STR_MODULE_ABSTRACT             #language en-US "A shell application that
> triggers capsule update process."
> +
> +#string STR_MODULE_DESCRIPTION          #language en-US "This application can trigger
> capsule update process. It can also generate capsule image, or dump capsule variable
> information."
> +
> diff --git a/MdeModulePkg/Application/CapsuleApp/CapsuleAppExtra.uni
> b/MdeModulePkg/Application/CapsuleApp/CapsuleAppExtra.uni
> new file mode 100644
> index 0000000..b5a8840
> --- /dev/null
> +++ b/MdeModulePkg/Application/CapsuleApp/CapsuleAppExtra.uni
> @@ -0,0 +1,19 @@
> +// /** @file
> +// CapsuleApp Localized Strings and Content
> +//
> +// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
> +//
> +// This program and the accompanying materials
> +// are licensed and made available under the terms and conditions of the BSD License
> +// which accompanies this distribution. The full text of the license may be found at
> +// http://opensource.org/licenses/bsd-license.php
> +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +//
> +// **/
> +
> +#string STR_PROPERTIES_MODULE_NAME
> +#language en-US
> +"Capsule Application"
> +
> +
> diff --git a/MdeModulePkg/Application/CapsuleApp/CapsuleDump.c
> b/MdeModulePkg/Application/CapsuleApp/CapsuleDump.c
> new file mode 100644
> index 0000000..c56f41f
> --- /dev/null
> +++ b/MdeModulePkg/Application/CapsuleApp/CapsuleDump.c
> @@ -0,0 +1,840 @@
> +/** @file
> +  Dump Capsule image information.
> +
> +  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the BSD License
> +  which accompanies this distribution.  The full text of the license may be found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +
> +**/
> +
> +#include <PiDxe.h>
> +#include <Library/BaseLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/UefiRuntimeServicesTableLib.h>
> +#include <Library/UefiLib.h>
> +#include <Library/PrintLib.h>
> +#include <Library/EdkiiSystemCapsuleLib.h>
> +#include <Protocol/FirmwareManagement.h>
> +#include <Guid/ImageAuthentication.h>
> +#include <Guid/EdkiiSystemFmpCapsule.h>
> +#include <Guid/CapsuleReport.h>
> +#include <Guid/SystemResourceTable.h>
> +#include <Guid/FmpCapsule.h>
> +#include <IndustryStandard/WindowsUxCapsule.h>
> +
> +/**
> +  Read a file.
> +
> +  @param FileName        The file to be read.
> +  @param BufferSize      The file buffer size
> +  @param Buffer          The file buffer
> +
> +  @retval EFI_SUCCESS    Read file successfully
> +  @retval EFI_NOT_FOUND  File not found
> +**/
> +EFI_STATUS
> +ReadFileToBuffer(
> +  IN  CHAR16                               *FileName,
> +  OUT UINTN                                *BufferSize,
> +  OUT VOID                                 **Buffer
> +  );
> +
> +extern UINTN  Argc;
> +extern CHAR16 *Argv[];
> +
> +/**
> +  Dump UX capsule information.
> +
> +  @param CapsuleHeader      The UX capsule header
> +**/
> +VOID
> +DumpUxCapsule(
> +  IN EFI_CAPSULE_HEADER  *CapsuleHeader
> +  )
> +{
> +  EFI_DISPLAY_CAPSULE                           *DisplayCapsule;
> +  DisplayCapsule = (EFI_DISPLAY_CAPSULE *)CapsuleHeader;
> +  Print(L"[UxCapusule]\n");
> +  Print(L"CapsuleHeader:\n");
> +  Print(L"  CapsuleGuid      - %g\n", &DisplayCapsule->CapsuleHeader.CapsuleGuid);
> +  Print(L"  HeaderSize       - 0x%x\n", DisplayCapsule->CapsuleHeader.HeaderSize);
> +  Print(L"  Flags            - 0x%x\n", DisplayCapsule->CapsuleHeader.Flags);
> +  Print(L"  CapsuleImageSize - 0x%x\n", DisplayCapsule-
> >CapsuleHeader.CapsuleImageSize);
> +  Print(L"ImagePayload:\n");
> +  Print(L"  Version          - 0x%x\n", DisplayCapsule->ImagePayload.Version);
> +  Print(L"  Checksum         - 0x%x\n", DisplayCapsule->ImagePayload.Checksum);
> +  Print(L"  ImageType        - 0x%x\n", DisplayCapsule->ImagePayload.ImageType);
> +  Print(L"  Mode             - 0x%x\n", DisplayCapsule->ImagePayload.Mode);
> +  Print(L"  OffsetX          - 0x%x\n", DisplayCapsule->ImagePayload.OffsetX);
> +  Print(L"  OffsetY          - 0x%x\n", DisplayCapsule->ImagePayload.OffsetY);
> +}
> +
> +/**
> +  Dump FMP image authentication information.
> +
> +  @param Image      The FMP capsule image
> +  @param ImageSize  The size of the FMP capsule image in bytes.
> +
> +  @return the size of FMP authentication.
> +**/
> +UINTN
> +DumpImageAuthentication(
> +  IN VOID   *Image,
> +  IN UINTN  ImageSize
> +  )
> +{
> +  EFI_FIRMWARE_IMAGE_AUTHENTICATION             *ImageAuthentication;
> +
> +  ImageAuthentication = Image;
> +  if (CompareGuid(&ImageAuthentication->AuthInfo.CertType, &gEfiCertPkcs7Guid) ||
> +      CompareGuid(&ImageAuthentication->AuthInfo.CertType,
> &gEfiCertTypeRsa2048Sha256Guid)) {
> +    Print(L"[ImageAuthentication]\n");
> +    Print(L"  MonotonicCount   - 0x%lx\n", ImageAuthentication->MonotonicCount);
> +    Print(L"WIN_CERTIFICATE:\n");
> +    Print(L"  dwLength         - 0x%x\n", ImageAuthentication->AuthInfo.Hdr.dwLength);
> +    Print(L"  wRevision        - 0x%x\n", ImageAuthentication-
> >AuthInfo.Hdr.wRevision);
> +    Print(L"  wCertificateType - 0x%x\n", ImageAuthentication-
> >AuthInfo.Hdr.wCertificateType);
> +    Print(L"  CertType         - %g\n", &ImageAuthentication->AuthInfo.CertType);
> +    return sizeof(ImageAuthentication->MonotonicCount) + ImageAuthentication-
> >AuthInfo.Hdr.dwLength;
> +  } else {
> +    return 0;
> +  }
> +}
> +
> +/**
> +  Dump EDKII system FMP capsule.
> +
> +  @param Image      The EDKII system FMP capsule.
> +  @param ImageSize  The size of the EDKII system FMP capsule in bytes.
> +**/
> +VOID
> +DumpEdkiiSystemFmpCapsule(
> +  IN VOID   *Image,
> +  IN UINTN  ImageSize
> +  )
> +{
> +  UINTN                                         ImageOffset;
> +  VOID                                          *BiosImage;
> +  UINTN                                         BiosImageSize;
> +  BOOLEAN                                       Result;
> +  EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR        *TempImageFmpInfo;
> +  EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR        *ImageFmpInfo;
> +  UINTN                                         ImageFmpInfoSize;
> +
> +  //
> +  // We do not know if there is EFI_FIRMWARE_IMAGE_AUTHENTICATION.
> +  // so just *try* to parse it
> +  //
> +  ImageOffset = DumpImageAuthentication(Image, ImageSize);
> +  Image = (UINT8 *)Image + ImageOffset;
> +  ImageSize -= ImageOffset;
> +  Print(L"[Image]\n");
> +  Print(L"  ImageSize   - 0x%x\n", ImageSize);
> +
> +  Result = ExtractConfigImage(Image, ImageSize, &BiosImage, &BiosImageSize);
> +  if (Result) {
> +    Print(L"  ConfigFileSize  - 0x%x\n", BiosImageSize);
> +  }
> +  Result = ExtractDriverFvImage(Image, ImageSize, &BiosImage, &BiosImageSize);
> +  if (Result) {
> +    Print(L"  DriverFvSize    - 0x%x\n", BiosImageSize);
> +  }
> +  Result = ExtractSystemFirmwareImage(Image, ImageSize, &BiosImage, &BiosImageSize);
> +  if (Result) {
> +    Print(L"  BiosImageSize   - 0x%x\n", BiosImageSize);
> +  }
> +  Result = ExtractSystemFirmwareImageFmpInfo(BiosImage, BiosImageSize,
> &TempImageFmpInfo, &ImageFmpInfoSize);
> +  if (Result) {
> +    ImageFmpInfo = AllocateCopyPool(ImageFmpInfoSize, TempImageFmpInfo);
> +    if (ImageFmpInfo != NULL) {
> +      Print(L"[ImageFmpInfo]\n");
> +      Print(L"  Signature                      - 0x%x\n", ImageFmpInfo->Signature);
> +      Print(L"  HeaderLength                   - 0x%x\n", ImageFmpInfo->HeaderLength);
> +      Print(L"  Length                         - 0x%x\n", ImageFmpInfo->Length);
> +      Print(L"  PackageVersion                 - 0x%x\n", ImageFmpInfo-
> >PackageVersion);
> +      Print(L"  PackageVersionNameStringOffset - 0x%x\n", ImageFmpInfo-
> >PackageVersionNameStringOffset);
> +      if (ImageFmpInfo->PackageVersionNameStringOffset != 0) {
> +        Print(L"                                 - %s\n", (UINT8 *)ImageFmpInfo +
> ImageFmpInfo->PackageVersionNameStringOffset);
> +      }
> +      Print(L"  ImageIndex                     - 0x%x\n", ImageFmpInfo->ImageIndex);
> +      Print(L"  ImageTypeId                    - %g\n", &ImageFmpInfo->ImageTypeId);
> +      Print(L"  ImageId                        - 0x%lx\n", ImageFmpInfo->ImageId);
> +      Print(L"  ImageIdNameStringOffset        - 0x%x\n", ImageFmpInfo-
> >ImageIdNameStringOffset);
> +      if (ImageFmpInfo->ImageIdNameStringOffset != 0) {
> +        Print(L"                                 - %s\n", (UINT8 *)ImageFmpInfo +
> ImageFmpInfo->ImageIdNameStringOffset);
> +      }
> +      Print(L"  Version                        - 0x%x\n", ImageFmpInfo->Version);
> +      Print(L"  VersionNameStringOffset        - 0x%x\n", ImageFmpInfo-
> >VersionNameStringOffset);
> +      if (ImageFmpInfo->VersionNameStringOffset != 0) {
> +        Print(L"                                 - %s\n", (UINT8 *)ImageFmpInfo +
> ImageFmpInfo->VersionNameStringOffset);
> +      }
> +      Print(L"  Size                           - 0x%lx\n", ImageFmpInfo->Size);
> +      Print(L"  AttributesSupported            - 0x%lx\n", ImageFmpInfo-
> >AttributesSupported);
> +      Print(L"  AttributesSetting              - 0x%lx\n", ImageFmpInfo-
> >AttributesSetting);
> +      Print(L"  Compatibilities                - 0x%lx\n", ImageFmpInfo-
> >Compatibilities);
> +      Print(L"  LowestSupportedImageVersion    - 0x%x\n", ImageFmpInfo-
> >LowestSupportedImageVersion);
> +      Print(L"  LastAttemptVersion             - 0x%x\n", ImageFmpInfo-
> >LastAttemptVersion);
> +      Print(L"  LastAttemptStatus              - 0x%x\n", ImageFmpInfo-
> >LastAttemptStatus);
> +      Print(L"  HardwareInstance               - 0x%lx\n", ImageFmpInfo-
> >HardwareInstance);
> +      Print(L"  Version                        - 0x%x\n", ImageFmpInfo->Version);
> +      FreePool(ImageFmpInfo);
> +    }
> +  }
> +}
> +
> +/**
> +  Dump a non-nested FMP capsule.
> +
> +  @param  CapsuleHeader  A pointer to CapsuleHeader
> +  @param  IsSystemFmp    If it is a system FMP
> +**/
> +VOID
> +DumpFmpCapsule(
> +  IN EFI_CAPSULE_HEADER  *CapsuleHeader,
> +  IN BOOLEAN             IsSystemFmp
> +  )
> +{
> +  EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER        *FmpCapsuleHeader;
> +  UINT64                                        *ItemOffsetList;
> +  UINTN                                         Index;
> +  UINTN                                         Count;
> +  EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER  *FmpImageHeader;
> +  VOID                                          *Image;
> +
> +  Print(L"[FmpCapusule]\n");
> +  Print(L"CapsuleHeader:\n");
> +  Print(L"  CapsuleGuid      - %g\n", &CapsuleHeader->CapsuleGuid);
> +  Print(L"  HeaderSize       - 0x%x\n", CapsuleHeader->HeaderSize);
> +  Print(L"  Flags            - 0x%x\n", CapsuleHeader->Flags);
> +  Print(L"  CapsuleImageSize - 0x%x\n", CapsuleHeader->CapsuleImageSize);
> +
> +  FmpCapsuleHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *)((UINT8 *)CapsuleHeader
> + CapsuleHeader->HeaderSize);
> +  ItemOffsetList = (UINT64 *)(FmpCapsuleHeader + 1);
> +  Print(L"FmpHeader:\n");
> +  Print(L"  Version             - 0x%x\n", FmpCapsuleHeader->Version);
> +  Print(L"  EmbeddedDriverCount - 0x%x\n", FmpCapsuleHeader->EmbeddedDriverCount);
> +  Print(L"  PayloadItemCount    - 0x%x\n", FmpCapsuleHeader->PayloadItemCount);
> +  Count = FmpCapsuleHeader->EmbeddedDriverCount + FmpCapsuleHeader->PayloadItemCount;
> +  for (Index = 0; Index < Count; Index++) {
> +    Print(L"  Offset[%d]           - 0x%x\n", Index, ItemOffsetList[Index]);
> +  }
> +
> +  for (Index = FmpCapsuleHeader->EmbeddedDriverCount; Index < Count; Index++) {
> +    Print(L"FmpPayload[%d] ImageHeader:\n", Index);
> +    FmpImageHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *)((UINT8
> *)FmpCapsuleHeader + ItemOffsetList[Index]);
> +    Print(L"  Version                - 0x%x\n", FmpImageHeader->Version);
> +    Print(L"  UpdateImageTypeId      - %g\n", &FmpImageHeader->UpdateImageTypeId);
> +    Print(L"  UpdateImageIndex       - 0x%x\n", FmpImageHeader->UpdateImageIndex);
> +    Print(L"  UpdateImageSize        - 0x%x\n", FmpImageHeader->UpdateImageSize);
> +    Print(L"  UpdateVendorCodeSize   - 0x%x\n", FmpImageHeader->UpdateVendorCodeSize);
> +    if (FmpImageHeader->Version >=
> EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {
> +      Print(L"  UpdateHardwareInstance - 0x%lx\n", FmpImageHeader-
> >UpdateHardwareInstance);
> +    }
> +    if (FmpImageHeader->Version >=
> EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {
> +      Image = (UINT8 *)(FmpImageHeader + 1);
> +    }  else {
> +      Image = (UINT8 *)FmpImageHeader +
> OFFSET_OF(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER, UpdateHardwareInstance);
> +    }
> +    if (IsSystemFmp) {
> +      DumpEdkiiSystemFmpCapsule(Image, FmpImageHeader->UpdateImageSize);
> +    }
> +  }
> +}
> +
> +/**
> +  Return if there is a FMP header below capsule header.
> +
> +  @param[in] CapsuleHeader A pointer to EFI_CAPSULE_HEADER
> +
> +  @retval TRUE  There is a FMP header below capsule header.
> +  @retval FALSE There is not a FMP header below capsule header
> +**/
> +BOOLEAN
> +IsNestedFmpCapsule(
> +  IN EFI_CAPSULE_HEADER         *CapsuleHeader
> +  )
> +{
> +  EFI_STATUS                 Status;
> +  EFI_SYSTEM_RESOURCE_TABLE  *Esrt;
> +  EFI_SYSTEM_RESOURCE_ENTRY  *EsrtEntry;
> +  UINTN                      Index;
> +  BOOLEAN                    EsrtGuidFound;
> +  EFI_CAPSULE_HEADER         *NestedCapsuleHeader;
> +  UINTN                      NestedCapsuleSize;
> +
> +  //
> +  // Check ESRT
> +  //
> +  EsrtGuidFound = FALSE;
> +  Status = EfiGetSystemConfigurationTable(&gEfiSystemResourceTableGuid, (VOID
> **)&Esrt);
> +  if (!EFI_ERROR(Status)) {
> +    EsrtEntry = (VOID *)(Esrt + 1);
> +    for (Index = 0; Index < Esrt->FwResourceCount; Index++, EsrtEntry++) {
> +      if (CompareGuid(&EsrtEntry->FwClass, &CapsuleHeader->CapsuleGuid)) {
> +        EsrtGuidFound = TRUE;
> +        break;
> +      }
> +    }
> +  }
> +
> +  if (!EsrtGuidFound) {
> +    return FALSE;
> +  }
> +
> +  //
> +  // Check nested capsule header
> +  // FMP GUID after ESRT one
> +  //
> +  NestedCapsuleHeader = (EFI_CAPSULE_HEADER *)((UINT8 *)CapsuleHeader + CapsuleHeader-
> >HeaderSize);
> +  NestedCapsuleSize = (UINTN)CapsuleHeader + CapsuleHeader->HeaderSize -
> (UINTN)NestedCapsuleHeader;
> +  if (NestedCapsuleSize < sizeof(EFI_CAPSULE_HEADER)) {
> +    return FALSE;
> +  }
> +  if (!CompareGuid(&NestedCapsuleHeader->CapsuleGuid, &gEfiFmpCapsuleGuid)) {
> +    return FALSE;
> +  }
> +  return TRUE;
> +}
> +
> +/**
> +  Dump capsule information
> +
> +  @retval EFI_SUCCESS            The capsule information is dumped.
> +  @retval EFI_UNSUPPORTED        Input parameter is not valid.
> +**/
> +EFI_STATUS
> +DumpCapsule(
> +  VOID
> +  )
> +{
> +  CHAR16                                        *CapsuleName;
> +  VOID                                          *Buffer;
> +  UINTN                                         FileSize;
> +  BOOLEAN                                       IsSystemFmp;
> +  EFI_CAPSULE_HEADER                            *CapsuleHeader;
> +  EFI_STATUS                                    Status;
> +
> +  if (Argc != 3) {
> +    Print(L"CapsuleApp: Invalid Parameter.\n");
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  IsSystemFmp = FALSE;
> +  if (StrCmp(Argv[1], L"-DS") == 0) {
> +    IsSystemFmp = TRUE;
> +  }
> +
> +  CapsuleName = Argv[2];
> +  Status = ReadFileToBuffer(CapsuleName, &FileSize, &Buffer);
> +  if (EFI_ERROR(Status)) {
> +    Print(L"CapsuleApp: Capsule (%s) is not found.\n", CapsuleName);
> +    goto Done;
> +  }
> +
> +  CapsuleHeader = Buffer;
> +  if (CompareGuid(&CapsuleHeader->CapsuleGuid, &gWindowsUxCapsuleGuid)) {
> +    DumpUxCapsule(CapsuleHeader);
> +    Status = EFI_SUCCESS;
> +    goto Done;
> +  }
> +
> +  if (CompareGuid(&CapsuleHeader->CapsuleGuid, &gEfiFmpCapsuleGuid)) {
> +    DumpFmpCapsule(CapsuleHeader, IsSystemFmp);
> +  }
> +  if (IsNestedFmpCapsule(CapsuleHeader)) {
> +    Print(L"[NestedCapusule]\n");
> +    Print(L"CapsuleHeader:\n");
> +    Print(L"  CapsuleGuid      - %g\n", &CapsuleHeader->CapsuleGuid);
> +    Print(L"  HeaderSize       - 0x%x\n", CapsuleHeader->HeaderSize);
> +    Print(L"  Flags            - 0x%x\n", CapsuleHeader->Flags);
> +    Print(L"  CapsuleImageSize - 0x%x\n", CapsuleHeader->CapsuleImageSize);
> +    DumpFmpCapsule((EFI_CAPSULE_HEADER *)((UINTN)CapsuleHeader + CapsuleHeader-
> >HeaderSize), IsSystemFmp);
> +  }
> +
> +Done:
> +  FreePool(Buffer);
> +  return Status;
> +}
> +
> +/**
> +  Dump capsule status variable.
> +
> +  @retval EFI_SUCCESS            The capsule status variable is dumped.
> +  @retval EFI_UNSUPPORTED        Input parameter is not valid.
> +**/
> +EFI_STATUS
> +DmpCapsuleStatusVariable(
> +  VOID
> +  )
> +{
> +  EFI_STATUS                          Status;
> +  UINT32                              Index;
> +  CHAR16                              CapsuleVarName[20];
> +  CHAR16                              *TempVarName;
> +  EFI_CAPSULE_RESULT_VARIABLE_HEADER  *CapsuleResult;
> +  EFI_CAPSULE_RESULT_VARIABLE_FMP     *CapsuleResultFmp;
> +  UINTN                               CapsuleFileNameSize;
> +  CHAR16                              CapsuleIndexData[12];
> +  CHAR16                              *CapsuleIndex;
> +
> +  Status = GetVariable2(
> +             L"CapsuleMax",
> +             &gEfiCapsuleReportGuid,
> +             (VOID **)&CapsuleIndex,
> +             NULL
> +             );
> +  if (!EFI_ERROR(Status)) {
> +    CopyMem(CapsuleIndexData, CapsuleIndex, 11 * sizeof(CHAR16));
> +    CapsuleIndexData[11] = 0;
> +    Print(L"CapsuleMax - %s\n", CapsuleIndexData);
> +    FreePool(CapsuleIndex);
> +  }
> +  Status = GetVariable2(
> +             L"CapsuleLast",
> +             &gEfiCapsuleReportGuid,
> +             (VOID **)&CapsuleIndex,
> +             NULL
> +             );
> +  if (!EFI_ERROR(Status)) {
> +    CopyMem(CapsuleIndexData, CapsuleIndex, 11 * sizeof(CHAR16));
> +    CapsuleIndexData[11] = 0;
> +    Print(L"CapsuleLast - %s\n", CapsuleIndexData);
> +    FreePool(CapsuleIndex);
> +  }
> +
> +
> +  StrCpyS (CapsuleVarName, sizeof(CapsuleVarName)/sizeof(CapsuleVarName[0]),
> L"Capsule");
> +  TempVarName = CapsuleVarName + StrLen (CapsuleVarName);
> +  Index = 0;
> +
> +  while (TRUE) {
> +    UnicodeSPrint (TempVarName, 5 * sizeof(CHAR16), L"%04x", Index);
> +
> +    Status = GetVariable2 (
> +               CapsuleVarName,
> +               &gEfiCapsuleReportGuid,
> +               (VOID **) &CapsuleResult,
> +               NULL
> +               );
> +    if (Status == EFI_NOT_FOUND) {
> +      break;
> +    } else if (EFI_ERROR(Status)) {
> +      continue;
> +    }
> +
> +    //
> +    // display capsule process status
> +    //
> +    if (CapsuleResult->VariableTotalSize >=
> sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER)) {
> +      Print (L"CapsuleName: %s\n", CapsuleVarName);
> +      Print (L"  Capsule Guid: %g\n", &CapsuleResult->CapsuleGuid);
> +      Print (L"  Capsule ProcessedTime: %t\n", &CapsuleResult->CapsuleProcessed);
> +      Print (L"  Capsule Status: %r\n", CapsuleResult->CapsuleStatus);
> +    }
> +
> +    if (CompareGuid(&CapsuleResult->CapsuleGuid, &gEfiFmpCapsuleGuid)) {
> +      if (CapsuleResult->VariableTotalSize >=
> sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER) + sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP)) {
> +        CapsuleResultFmp = (EFI_CAPSULE_RESULT_VARIABLE_FMP *)(CapsuleResult + 1);
> +        Print(L"  Capsule FMP Version: 0x%x\n", CapsuleResultFmp->Version);
> +        Print(L"  Capsule FMP PayloadIndex: 0x%x\n", CapsuleResultFmp->PayloadIndex);
> +        Print(L"  Capsule FMP UpdateImageIndex: 0x%x\n", CapsuleResultFmp-
> >UpdateImageIndex);
> +        Print(L"  Capsule FMP UpdateImageTypeId: %g\n", &CapsuleResultFmp-
> >UpdateImageTypeId);
> +        if (CapsuleResult->VariableTotalSize >
> sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER) + sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP)) {
> +          Print(L"  Capsule FMP CapsuleFileName: %s\n", (CapsuleResultFmp + 1));
> +          CapsuleFileNameSize = StrSize((CHAR16 *)(CapsuleResultFmp + 1));
> +          if (CapsuleResult->VariableTotalSize >
> sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER) + sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP) +
> CapsuleFileNameSize) {
> +            Print(L"  Capsule FMP CapsuleTarget: %s\n", (UINT8 *)(CapsuleResultFmp +
> 1) + CapsuleFileNameSize);
> +          }
> +        }
> +      }
> +    }
> +
> +    FreePool(CapsuleResult);
> +
> +    Index++;
> +    if (Index > 0xFFFF) {
> +      break;
> +    }
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +CHAR8 *mFwTypeString[] = {
> +  "Unknown",
> +  "SystemFirmware",
> +  "DeviceFirmware",
> +  "UefiDriver",
> +};
> +
> +CHAR8 *mLastAttemptStatusString[] = {
> +  "Success",
> +  "Error: Unsuccessful",
> +  "Error: Insufficient Resources",
> +  "Error: Incorrect Version",
> +  "Error: Invalid Format",
> +  "Error: Auth Error",
> +  "Error: Power Event AC",
> +  "Error: Power Event Battery",
> +};
> +
> +/**
> +  Convert FwType to a string.
> +
> +  @param FwType  FwType in ESRT
> +
> +  @return a string for FwType.
> +**/
> +CHAR8 *
> +FwTypeToString(
> +  IN UINT32 FwType
> +  )
> +{
> +  if (FwType < sizeof(mFwTypeString) / sizeof(mFwTypeString[0])) {
> +    return mFwTypeString[FwType];
> +  } else {
> +    return "Invalid";
> +  }
> +}
> +
> +/**
> +  Convert LastAttemptStatus to a string.
> +
> +  @param LastAttemptStatus  LastAttemptStatus in FMP or ESRT
> +
> +  @return a string for LastAttemptStatus.
> +**/
> +CHAR8 *
> +LastAttemptStatusToString(
> +  IN UINT32 LastAttemptStatus
> +  )
> +{
> +  if (LastAttemptStatus < sizeof(mLastAttemptStatusString) /
> sizeof(mLastAttemptStatusString[0])) {
> +    return mLastAttemptStatusString[LastAttemptStatus];
> +  } else {
> +    return "Error: Unknown";
> +  }
> +}
> +
> +/**
> +  Dump ESRT entry.
> +
> +  @param EsrtEntry  ESRT entry
> +**/
> +VOID
> +DumpEsrtEntry(
> +  IN EFI_SYSTEM_RESOURCE_ENTRY  *EsrtEntry
> +  )
> +{
> +  Print(L"  FwClass                  - %g\n", &EsrtEntry->FwClass);
> +  Print(L"  FwType                   - 0x%x (%a)\n", EsrtEntry->FwType,
> FwTypeToString(EsrtEntry->FwType));
> +  Print(L"  FwVersion                - 0x%x\n", EsrtEntry->FwVersion);
> +  Print(L"  LowestSupportedFwVersion - 0x%x\n", EsrtEntry->LowestSupportedFwVersion);
> +  Print(L"  CapsuleFlags             - 0x%x\n", EsrtEntry->CapsuleFlags);
> +  Print(L"    PERSIST_ACROSS_RESET   - 0x%x\n", EsrtEntry->CapsuleFlags &
> CAPSULE_FLAGS_PERSIST_ACROSS_RESET);
> +  Print(L"    POPULATE_SYSTEM_TABLE  - 0x%x\n", EsrtEntry->CapsuleFlags &
> CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE);
> +  Print(L"    INITIATE_RESET         - 0x%x\n", EsrtEntry->CapsuleFlags &
> CAPSULE_FLAGS_INITIATE_RESET);
> +  Print(L"  LastAttemptVersion       - 0x%x\n", EsrtEntry->LastAttemptVersion);
> +  Print(L"  LastAttemptStatus        - 0x%x (%a)\n", EsrtEntry->LastAttemptStatus,
> LastAttemptStatusToString(EsrtEntry->LastAttemptStatus));
> +}
> +
> +/**
> +  Dump ESRT table.
> +
> +  @param Esrt  ESRT table
> +**/
> +VOID
> +DumpEsrt(
> +  IN EFI_SYSTEM_RESOURCE_TABLE  *Esrt
> +  )
> +{
> +  UINTN                      Index;
> +  EFI_SYSTEM_RESOURCE_ENTRY  *EsrtEntry;
> +
> +  Print(L"EFI_SYSTEM_RESOURCE_TABLE:\n");
> +  Print(L"FwResourceCount    - 0x%x\n", Esrt->FwResourceCount);
> +  Print(L"FwResourceCountMax - 0x%x\n", Esrt->FwResourceCountMax);
> +  Print(L"FwResourceVersion  - 0x%lx\n", Esrt->FwResourceVersion);
> +
> +  EsrtEntry = (VOID *)(Esrt + 1);
> +  for (Index = 0; Index < Esrt->FwResourceCount; Index++) {
> +    Print(L"EFI_SYSTEM_RESOURCE_ENTRY (%d):\n", Index);
> +    DumpEsrtEntry(EsrtEntry);
> +    EsrtEntry++;
> +  }
> +}
> +
> +/**
> +  Dump ESRT info.
> +**/
> +VOID
> +DumpEsrtData (
> +  VOID
> +  )
> +{
> +  EFI_STATUS                 Status;
> +  EFI_SYSTEM_RESOURCE_TABLE  *Esrt;
> +
> +  Print(L"##############\n");
> +  Print(L"# ESRT TABLE #\n");
> +  Print(L"##############\n");
> +
> +  Status = EfiGetSystemConfigurationTable (&gEfiSystemResourceTableGuid, (VOID
> **)&Esrt);
> +  if (EFI_ERROR(Status)) {
> +    Print(L"ESRT - %r\n", Status);
> +    return;
> +  }
> +  DumpEsrt(Esrt);
> +  Print(L"\n");
> +}
> +
> +/**
> +  Dump FMP information.
> +
> +  @param ImageInfoSize       The size of ImageInfo, in bytes.
> +  @param ImageInfo           A pointer to EFI_FIRMWARE_IMAGE_DESCRIPTOR.
> +  @param DescriptorVersion   The version of EFI_FIRMWARE_IMAGE_DESCRIPTOR.
> +  @param DescriptorCount     The count of EFI_FIRMWARE_IMAGE_DESCRIPTOR.
> +  @param DescriptorSize      The size of an individual EFI_FIRMWARE_IMAGE_DESCRIPTOR,
> in bytes.
> +  @param PackageVersion      The version of package.
> +  @param PackageVersionName  The version name of package.
> +**/
> +VOID
> +DumpFmpImageInfo(
> +  IN UINTN                           ImageInfoSize,
> +  IN EFI_FIRMWARE_IMAGE_DESCRIPTOR   *ImageInfo,
> +  IN UINT32                          DescriptorVersion,
> +  IN UINT8                           DescriptorCount,
> +  IN UINTN                           DescriptorSize,
> +  IN UINT32                          PackageVersion,
> +  IN CHAR16                          *PackageVersionName
> +  )
> +{
> +  EFI_FIRMWARE_IMAGE_DESCRIPTOR                 *CurrentImageInfo;
> +  UINTN                                         Index;
> +
> +  Print(L"  DescriptorVersion  - 0x%x\n", DescriptorVersion);
> +  Print(L"  DescriptorCount    - 0x%x\n", DescriptorCount);
> +  Print(L"  DescriptorSize     - 0x%x\n", DescriptorSize);
> +  Print(L"  PackageVersion     - 0x%x\n", PackageVersion);
> +  Print(L"  PackageVersionName - \"%s\"\n", PackageVersionName);
> +  CurrentImageInfo = ImageInfo;
> +  for (Index = 0; Index < DescriptorCount; Index++) {
> +    Print(L"  ImageDescriptor (%d)\n", Index);
> +    Print(L"    ImageIndex                  - 0x%x\n", CurrentImageInfo->ImageIndex);
> +    Print(L"    ImageTypeId                 - %g\n", &CurrentImageInfo->ImageTypeId);
> +    Print(L"    ImageId                     - 0x%lx\n", CurrentImageInfo->ImageId);
> +    Print(L"    ImageIdName                 - \"%s\"\n", CurrentImageInfo-
> >ImageIdName);
> +    Print(L"    Version                     - 0x%x\n", CurrentImageInfo->Version);
> +    Print(L"    VersionName                 - \"%s\"\n", CurrentImageInfo-
> >VersionName);
> +    Print(L"    Size                        - 0x%x\n", CurrentImageInfo->Size);
> +    Print(L"    AttributesSupported         - 0x%lx\n", CurrentImageInfo-
> >AttributesSupported);
> +    Print(L"      IMAGE_UPDATABLE           - 0x%lx\n", CurrentImageInfo-
> >AttributesSupported & IMAGE_ATTRIBUTE_IMAGE_UPDATABLE);
> +    Print(L"      RESET_REQUIRED            - 0x%lx\n", CurrentImageInfo-
> >AttributesSupported & IMAGE_ATTRIBUTE_RESET_REQUIRED);
> +    Print(L"      AUTHENTICATION_REQUIRED   - 0x%lx\n", CurrentImageInfo-
> >AttributesSupported & IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);
> +    Print(L"      IN_USE                    - 0x%lx\n", CurrentImageInfo-
> >AttributesSupported & IMAGE_ATTRIBUTE_IN_USE);
> +    Print(L"      UEFI_IMAGE                - 0x%lx\n", CurrentImageInfo-
> >AttributesSupported & IMAGE_ATTRIBUTE_UEFI_IMAGE);
> +    Print(L"    AttributesSetting           - 0x%lx\n", CurrentImageInfo-
> >AttributesSetting);
> +    Print(L"      IMAGE_UPDATABLE           - 0x%lx\n", CurrentImageInfo-
> >AttributesSetting & IMAGE_ATTRIBUTE_IMAGE_UPDATABLE);
> +    Print(L"      RESET_REQUIRED            - 0x%lx\n", CurrentImageInfo-
> >AttributesSetting & IMAGE_ATTRIBUTE_RESET_REQUIRED);
> +    Print(L"      AUTHENTICATION_REQUIRED   - 0x%lx\n", CurrentImageInfo-
> >AttributesSetting & IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);
> +    Print(L"      IN_USE                    - 0x%lx\n", CurrentImageInfo-
> >AttributesSetting & IMAGE_ATTRIBUTE_IN_USE);
> +    Print(L"      UEFI_IMAGE                - 0x%lx\n", CurrentImageInfo-
> >AttributesSetting & IMAGE_ATTRIBUTE_UEFI_IMAGE);
> +    Print(L"    Compatibilities             - 0x%lx\n", CurrentImageInfo-
> >Compatibilities);
> +    Print(L"      COMPATIB_CHECK_SUPPORTED  - 0x%lx\n", CurrentImageInfo-
> >Compatibilities & IMAGE_COMPATIBILITY_CHECK_SUPPORTED);
> +    if (DescriptorVersion > 1) {
> +      Print(L"    LowestSupportedImageVersion - 0x%x\n", CurrentImageInfo-
> >LowestSupportedImageVersion);
> +      if (DescriptorVersion > 2) {
> +        Print(L"    LastAttemptVersion          - 0x%x\n", CurrentImageInfo-
> >LastAttemptVersion);
> +        Print(L"    LastAttemptStatus           - 0x%x (%a)\n", CurrentImageInfo-
> >LastAttemptStatus, LastAttemptStatusToString(CurrentImageInfo->LastAttemptStatus));
> +        Print(L"    HardwareInstance            - 0x%lx\n", CurrentImageInfo-
> >HardwareInstance);
> +      }
> +    }
> +    //
> +    // Use DescriptorSize to move ImageInfo Pointer to stay compatible with different
> ImageInfo version
> +    //
> +    CurrentImageInfo = (EFI_FIRMWARE_IMAGE_DESCRIPTOR *)((UINT8 *)CurrentImageInfo +
> DescriptorSize);
> +  }
> +}
> +
> +/**
> +  Dump FMP package information.
> +
> +  @param PackageVersion             The version of package.
> +  @param PackageVersionName         The version name of package.
> +  @param PackageVersionNameMaxLen   The maximum length of PackageVersionName.
> +  @param AttributesSupported        Package attributes that are supported by this
> device.
> +  @param AttributesSetting          Package attributes.
> +**/
> +VOID
> +DumpFmpPackageInfo(
> +  IN UINT32                           PackageVersion,
> +  IN CHAR16                           *PackageVersionName,
> +  IN UINT32                           PackageVersionNameMaxLen,
> +  IN UINT64                           AttributesSupported,
> +  IN UINT64                           AttributesSetting
> +  )
> +{
> +  Print(L"  PackageVersion              - 0x%x\n", PackageVersion);
> +  Print(L"  PackageVersionName          - \"%s\"\n", PackageVersionName);
> +  Print(L"  PackageVersionNameMaxLen    - 0x%x\n", PackageVersionNameMaxLen);
> +  Print(L"  AttributesSupported         - 0x%lx\n", AttributesSupported);
> +  Print(L"    IMAGE_UPDATABLE           - 0x%lx\n", AttributesSupported &
> IMAGE_ATTRIBUTE_IMAGE_UPDATABLE);
> +  Print(L"    RESET_REQUIRED            - 0x%lx\n", AttributesSupported &
> IMAGE_ATTRIBUTE_RESET_REQUIRED);
> +  Print(L"    AUTHENTICATION_REQUIRED   - 0x%lx\n", AttributesSupported &
> IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);
> +  Print(L"  AttributesSetting           - 0x%lx\n", AttributesSetting);
> +  Print(L"    IMAGE_UPDATABLE           - 0x%lx\n", AttributesSetting &
> IMAGE_ATTRIBUTE_IMAGE_UPDATABLE);
> +  Print(L"    RESET_REQUIRED            - 0x%lx\n", AttributesSetting &
> IMAGE_ATTRIBUTE_RESET_REQUIRED);
> +  Print(L"    AUTHENTICATION_REQUIRED   - 0x%lx\n", AttributesSetting &
> IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);
> +}
> +
> +/**
> +  Dump FMP protocol info.
> +**/
> +VOID
> +DumpFmpData (
> +  VOID
> +  )
> +{
> +  EFI_STATUS                                    Status;
> +  EFI_FIRMWARE_MANAGEMENT_PROTOCOL              *Fmp;
> +  EFI_HANDLE                                    *HandleBuffer;
> +  UINTN                                         NumberOfHandles;
> +  UINTN                                         Index;
> +  EFI_FIRMWARE_IMAGE_DESCRIPTOR                 *FmpImageInfoBuf;
> +  UINTN                                         ImageInfoSize;
> +  UINT32                                        FmpImageInfoDescriptorVer;
> +  UINT8                                         FmpImageInfoCount;
> +  UINTN                                         DescriptorSize;
> +  UINT32                                        PackageVersion;
> +  CHAR16                                        *PackageVersionName;
> +  UINT32                                        PackageVersionNameMaxLen;
> +  UINT64                                        AttributesSupported;
> +  UINT64                                        AttributesSetting;
> +
> +  Print(L"############\n");
> +  Print(L"# FMP DATA #\n");
> +  Print(L"############\n");
> +  Status = gBS->LocateHandleBuffer (
> +                  ByProtocol,
> +                  &gEfiFirmwareManagementProtocolGuid,
> +                  NULL,
> +                  &NumberOfHandles,
> +                  &HandleBuffer
> +                  );
> +  if (EFI_ERROR(Status)) {
> +    Print(L"FMP protocol - %r\n", EFI_NOT_FOUND);
> +    return;
> +  }
> +
> +  for (Index = 0; Index < NumberOfHandles; Index++) {
> +    Status = gBS->HandleProtocol(
> +                    HandleBuffer[Index],
> +                    &gEfiFirmwareManagementProtocolGuid,
> +                    (VOID **)&Fmp
> +                    );
> +    if (EFI_ERROR(Status)) {
> +      continue;
> +    }
> +
> +    ImageInfoSize = 0;
> +    Status = Fmp->GetImageInfo (
> +                    Fmp,
> +                    &ImageInfoSize,
> +                    NULL,
> +                    NULL,
> +                    NULL,
> +                    NULL,
> +                    NULL,
> +                    NULL
> +                    );
> +    if (Status != EFI_BUFFER_TOO_SMALL) {
> +      continue;
> +    }
> +
> +    FmpImageInfoBuf = NULL;
> +    FmpImageInfoBuf = AllocateZeroPool (ImageInfoSize);
> +    if (FmpImageInfoBuf == NULL) {
> +      Status = EFI_OUT_OF_RESOURCES;
> +      goto EXIT;
> +    }
> +
> +    PackageVersionName = NULL;
> +    Status = Fmp->GetImageInfo (
> +                    Fmp,
> +                    &ImageInfoSize,               // ImageInfoSize
> +                    FmpImageInfoBuf,              // ImageInfo
> +                    &FmpImageInfoDescriptorVer,   // DescriptorVersion
> +                    &FmpImageInfoCount,           // DescriptorCount
> +                    &DescriptorSize,              // DescriptorSize
> +                    &PackageVersion,              // PackageVersion
> +                    &PackageVersionName           // PackageVersionName
> +                    );
> +
> +    //
> +    // If FMP GetInformation interface failed, skip this resource
> +    //
> +    if (EFI_ERROR(Status)) {
> +      Print(L"FMP (%d) ImageInfo - %r\n", Index, Status);
> +      FreePool(FmpImageInfoBuf);
> +      continue;
> +    }
> +
> +    Print(L"FMP (%d) ImageInfo:\n", Index);
> +    DumpFmpImageInfo(
> +      ImageInfoSize,               // ImageInfoSize
> +      FmpImageInfoBuf,             // ImageInfo
> +      FmpImageInfoDescriptorVer,   // DescriptorVersion
> +      FmpImageInfoCount,           // DescriptorCount
> +      DescriptorSize,              // DescriptorSize
> +      PackageVersion,              // PackageVersion
> +      PackageVersionName           // PackageVersionName
> +      );
> +
> +    if (PackageVersionName != NULL) {
> +      FreePool(PackageVersionName);
> +    }
> +    FreePool(FmpImageInfoBuf);
> +
> +    //
> +    // Get package info
> +    //
> +    PackageVersionName = NULL;
> +    Status = Fmp->GetPackageInfo (
> +                    Fmp,
> +                    &PackageVersion,              // PackageVersion
> +                    &PackageVersionName,          // PackageVersionName
> +                    &PackageVersionNameMaxLen,    // PackageVersionNameMaxLen
> +                    &AttributesSupported,         // AttributesSupported
> +                    &AttributesSetting            // AttributesSetting
> +                    );
> +    if (EFI_ERROR(Status)) {
> +      Print(L"FMP (%d) PackageInfo - %r\n", Index, Status);
> +    } else {
> +      Print(L"FMP (%d) ImageInfo:\n", Index);
> +      DumpFmpPackageInfo(
> +        PackageVersion,              // PackageVersion
> +        PackageVersionName,          // PackageVersionName
> +        PackageVersionNameMaxLen,    // PackageVersionNameMaxLen
> +        AttributesSupported,         // AttributesSupported
> +        AttributesSetting            // AttributesSetting
> +        );
> +
> +      if (PackageVersionName != NULL) {
> +        FreePool(PackageVersionName);
> +      }
> +    }
> +  }
> +  Print(L"\n");
> +
> +EXIT:
> +  FreePool(HandleBuffer);
> +}
> --
> 2.7.4.windows.1
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>
https://lists.01.org/mailman/listinfo/edk2-devel


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

* Re: [PATCH 04/45] MdeModulePkg/Include: Add IniParsingLib header.
  2016-09-21  6:44 ` [PATCH 04/45] MdeModulePkg/Include: Add IniParsingLib header Jiewen Yao
@ 2016-09-29  6:53   ` Ni, Ruiyu
  2016-09-29  7:10     ` Yao, Jiewen
  0 siblings, 1 reply; 83+ messages in thread
From: Ni, Ruiyu @ 2016-09-29  6:53 UTC (permalink / raw)
  To: Yao, Jiewen, edk2-devel@lists.01.org
  Cc: Kinney, Michael D, Tian, Feng, Zhang, Chao B, Gao, Liming,
	Zeng, Star

The function header of OpenDataFile doesn't match the actual prototype of this API.

And since it's IniParsingLib, how about using OpenIniFile/CloseIniFile? 

Regards,
Ray

>-----Original Message-----
>From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of Jiewen Yao
>Sent: Wednesday, September 21, 2016 2:45 PM
>To: edk2-devel@lists.01.org
>Cc: Kinney, Michael D <michael.d.kinney@intel.com>; Tian, Feng <feng.tian@intel.com>; Zhang, Chao B
><chao.b.zhang@intel.com>; Gao, Liming <liming.gao@intel.com>; Zeng, Star <star.zeng@intel.com>
>Subject: [edk2] [PATCH 04/45] MdeModulePkg/Include: Add IniParsingLib header.
>
>This library is used to parse the INI configuration file.
>The INI configuration file is used in EDKII capsule image to describe
>the capsule information.
>
>The INI file format is:
>================
>[SectionName]
>EntryName=EntryValue
>================
>
>Cc: Feng Tian <feng.tian@intel.com>
>Cc: Star Zeng <star.zeng@intel.com>
>Cc: Michael D Kinney <michael.d.kinney@intel.com>
>Cc: Liming Gao <liming.gao@intel.com>
>Cc: Chao Zhang <chao.b.zhang@intel.com>
>Contributed-under: TianoCore Contribution Agreement 1.0
>Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
>---
> MdeModulePkg/Include/Library/IniParsingLib.h | 153 ++++++++++++++++++++
> 1 file changed, 153 insertions(+)
>
>diff --git a/MdeModulePkg/Include/Library/IniParsingLib.h b/MdeModulePkg/Include/Library/IniParsingLib.h
>new file mode 100644
>index 0000000..e3ed18d
>--- /dev/null
>+++ b/MdeModulePkg/Include/Library/IniParsingLib.h
>@@ -0,0 +1,153 @@
>+/** @file
>+  INI configuration parsing library.
>+
>+  The INI file format is:
>+    ================
>+    [SectionName]
>+    EntryName=EntryValue
>+    ================
>+
>+Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
>+This program and the accompanying materials
>+are licensed and made available under the terms and conditions of the BSD License
>+which accompanies this distribution.  The full text of the license may be found at
>+http://opensource.org/licenses/bsd-license.php
>+
>+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
>+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
>+
>+**/
>+
>+
>+#ifndef __INI_PARSING_LIB_H__
>+#define __INI_PARSING_LIB_H__
>+
>+/**
>+  Open an INI config file and return a context.
>+
>+  @param DataBuffer      Config raw file buffer.
>+  @param BufferSize      Size of raw buffer.
>+
>+  @retval EFI_SUCCESS           Config data buffer is opened and context is returned.
>+  @retval EFI_OUT_OF_RESOURCES  No enough memory is allocated.
>+**/
>+VOID *
>+EFIAPI
>+OpenDataFile(
>+  IN      UINT8                         *DataBuffer,
>+  IN      UINTN                         BufferSize
>+  );
>+
>+/**
>+  Get section entry string value.
>+
>+  @param Context         INI Config file context.
>+  @param SectionName     Section name.
>+  @param EntryName       Section entry name.
>+  @param EntryValue      Point to the got entry string value.
>+
>+  @retval EFI_SUCCESS    Section entry string value is got.
>+  @retval EFI_NOT_FOUND  Section is not found.
>+**/
>+EFI_STATUS
>+EFIAPI
>+GetStringFromDataFile(
>+  IN      VOID                          *Context,
>+  IN      CHAR8                         *SectionName,
>+  IN      CHAR8                         *EntryName,
>+  OUT     CHAR8                         **EntryValue
>+  );
>+
>+/**
>+  Get section entry GUID value.
>+
>+  @param Context         INI Config file context.
>+  @param SectionName     Section name.
>+  @param EntryName       Section entry name.
>+  @param Guid            Point to the got GUID value.
>+
>+  @retval EFI_SUCCESS    Section entry GUID value is got.
>+  @retval EFI_NOT_FOUND  Section is not found.
>+**/
>+EFI_STATUS
>+EFIAPI
>+GetGuidFromDataFile(
>+  IN      VOID                          *Context,
>+  IN      CHAR8                         *SectionName,
>+  IN      CHAR8                         *EntryName,
>+  OUT     EFI_GUID                      *Guid
>+  );
>+
>+/**
>+  Get section entry UINTN value.
>+
>+  @param Context         INI Config file context.
>+  @param SectionName     Section name.
>+  @param EntryName       Section entry name.
>+  @param Data            Point to the got UINTN value.
>+
>+  @retval EFI_SUCCESS    Section entry UINTN value is got.
>+  @retval EFI_NOT_FOUND  Section is not found.
>+**/
>+EFI_STATUS
>+EFIAPI
>+GetDecimalUintnFromDataFile(
>+  IN      VOID                          *Context,
>+  IN      CHAR8                         *SectionName,
>+  IN      CHAR8                         *EntryName,
>+  OUT     UINTN                         *Data
>+  );
>+
>+/**
>+  Get section entry heximal UINTN value.
>+
>+  @param Context         INI Config file context.
>+  @param SectionName     Section name.
>+  @param EntryName       Section entry name.
>+  @param Data            Point to the got heximal UINTN value.
>+
>+  @retval EFI_SUCCESS    Section entry heximal UINTN value is got.
>+  @retval EFI_NOT_FOUND  Section is not found.
>+**/
>+EFI_STATUS
>+EFIAPI
>+GetHexUintnFromDataFile(
>+  IN      VOID                          *Context,
>+  IN      CHAR8                         *SectionName,
>+  IN      CHAR8                         *EntryName,
>+  OUT     UINTN                         *Data
>+  );
>+
>+/**
>+  Get section entry heximal UINT64 value.
>+
>+  @param Context         INI Config file context.
>+  @param SectionName     Section name.
>+  @param EntryName       Section entry name.
>+  @param Data            Point to the got heximal UINT64 value.
>+
>+  @retval EFI_SUCCESS    Section entry heximal UINT64 value is got.
>+  @retval EFI_NOT_FOUND  Section is not found.
>+**/
>+EFI_STATUS
>+EFIAPI
>+GetHexUint64FromDataFile(
>+  IN      VOID                          *Context,
>+  IN      CHAR8                         *SectionName,
>+  IN      CHAR8                         *EntryName,
>+  OUT     UINT64                        *Data
>+  );
>+
>+/**
>+  Close an INI config file and free the context.
>+
>+  @param Context         INI Config file context.
>+**/
>+VOID
>+EFIAPI
>+CloseDataFile(
>+  IN      VOID                          *Context
>+  );
>+
>+#endif
>+
>--
>2.7.4.windows.1
>
>_______________________________________________
>edk2-devel mailing list
>edk2-devel@lists.01.org
>https://lists.01.org/mailman/listinfo/edk2-devel


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

* Re: [PATCH 04/45] MdeModulePkg/Include: Add IniParsingLib header.
  2016-09-29  6:53   ` Ni, Ruiyu
@ 2016-09-29  7:10     ` Yao, Jiewen
  0 siblings, 0 replies; 83+ messages in thread
From: Yao, Jiewen @ 2016-09-29  7:10 UTC (permalink / raw)
  To: Ni, Ruiyu, edk2-devel@lists.01.org
  Cc: Kinney, Michael D, Tian, Feng, Zhang, Chao B, Gao, Liming,
	Zeng, Star

Agree.

From: Ni, Ruiyu
Sent: Thursday, September 29, 2016 2:53 PM
To: Yao, Jiewen <jiewen.yao@intel.com>; edk2-devel@lists.01.org
Cc: Kinney, Michael D <michael.d.kinney@intel.com>; Tian, Feng <feng.tian@intel.com>; Zhang, Chao B <chao.b.zhang@intel.com>; Gao, Liming <liming.gao@intel.com>; Zeng, Star <star.zeng@intel.com>
Subject: RE: [edk2] [PATCH 04/45] MdeModulePkg/Include: Add IniParsingLib header.

The function header of OpenDataFile doesn't match the actual prototype of this API.

And since it's IniParsingLib, how about using OpenIniFile/CloseIniFile?

Regards,
Ray

>-----Original Message-----
>From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of Jiewen Yao
>Sent: Wednesday, September 21, 2016 2:45 PM
>To: edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>
>Cc: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>; Tian, Feng <feng.tian@intel.com<mailto:feng.tian@intel.com>>; Zhang, Chao B
><chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com>>; Gao, Liming <liming.gao@intel.com<mailto:liming.gao@intel.com>>; Zeng, Star <star.zeng@intel.com<mailto:star.zeng@intel.com>>
>Subject: [edk2] [PATCH 04/45] MdeModulePkg/Include: Add IniParsingLib header.
>
>This library is used to parse the INI configuration file.
>The INI configuration file is used in EDKII capsule image to describe
>the capsule information.
>
>The INI file format is:
>================
>[SectionName]
>EntryName=EntryValue
>================
>
>Cc: Feng Tian <feng.tian@intel.com<mailto:feng.tian@intel.com>>
>Cc: Star Zeng <star.zeng@intel.com<mailto:star.zeng@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 Zhang <chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com>>
>Contributed-under: TianoCore Contribution Agreement 1.0
>Signed-off-by: Jiewen Yao <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>
>---
> MdeModulePkg/Include/Library/IniParsingLib.h | 153 ++++++++++++++++++++
> 1 file changed, 153 insertions(+)
>
>diff --git a/MdeModulePkg/Include/Library/IniParsingLib.h b/MdeModulePkg/Include/Library/IniParsingLib.h
>new file mode 100644
>index 0000000..e3ed18d
>--- /dev/null
>+++ b/MdeModulePkg/Include/Library/IniParsingLib.h
>@@ -0,0 +1,153 @@
>+/** @file
>+  INI configuration parsing library.
>+
>+  The INI file format is:
>+    ================
>+    [SectionName]
>+    EntryName=EntryValue
>+    ================
>+
>+Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
>+This program and the accompanying materials
>+are licensed and made available under the terms and conditions of the BSD License
>+which accompanies this distribution.  The full text of the license may be found at
>+http://opensource.org/licenses/bsd-license.php
>+
>+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
>+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
>+
>+**/
>+
>+
>+#ifndef __INI_PARSING_LIB_H__
>+#define __INI_PARSING_LIB_H__
>+
>+/**
>+  Open an INI config file and return a context.
>+
>+  @param DataBuffer      Config raw file buffer.
>+  @param BufferSize      Size of raw buffer.
>+
>+  @retval EFI_SUCCESS           Config data buffer is opened and context is returned.
>+  @retval EFI_OUT_OF_RESOURCES  No enough memory is allocated.
>+**/
>+VOID *
>+EFIAPI
>+OpenDataFile(
>+  IN      UINT8                         *DataBuffer,
>+  IN      UINTN                         BufferSize
>+  );
>+
>+/**
>+  Get section entry string value.
>+
>+  @param Context         INI Config file context.
>+  @param SectionName     Section name.
>+  @param EntryName       Section entry name.
>+  @param EntryValue      Point to the got entry string value.
>+
>+  @retval EFI_SUCCESS    Section entry string value is got.
>+  @retval EFI_NOT_FOUND  Section is not found.
>+**/
>+EFI_STATUS
>+EFIAPI
>+GetStringFromDataFile(
>+  IN      VOID                          *Context,
>+  IN      CHAR8                         *SectionName,
>+  IN      CHAR8                         *EntryName,
>+  OUT     CHAR8                         **EntryValue
>+  );
>+
>+/**
>+  Get section entry GUID value.
>+
>+  @param Context         INI Config file context.
>+  @param SectionName     Section name.
>+  @param EntryName       Section entry name.
>+  @param Guid            Point to the got GUID value.
>+
>+  @retval EFI_SUCCESS    Section entry GUID value is got.
>+  @retval EFI_NOT_FOUND  Section is not found.
>+**/
>+EFI_STATUS
>+EFIAPI
>+GetGuidFromDataFile(
>+  IN      VOID                          *Context,
>+  IN      CHAR8                         *SectionName,
>+  IN      CHAR8                         *EntryName,
>+  OUT     EFI_GUID                      *Guid
>+  );
>+
>+/**
>+  Get section entry UINTN value.
>+
>+  @param Context         INI Config file context.
>+  @param SectionName     Section name.
>+  @param EntryName       Section entry name.
>+  @param Data            Point to the got UINTN value.
>+
>+  @retval EFI_SUCCESS    Section entry UINTN value is got.
>+  @retval EFI_NOT_FOUND  Section is not found.
>+**/
>+EFI_STATUS
>+EFIAPI
>+GetDecimalUintnFromDataFile(
>+  IN      VOID                          *Context,
>+  IN      CHAR8                         *SectionName,
>+  IN      CHAR8                         *EntryName,
>+  OUT     UINTN                         *Data
>+  );
>+
>+/**
>+  Get section entry heximal UINTN value.
>+
>+  @param Context         INI Config file context.
>+  @param SectionName     Section name.
>+  @param EntryName       Section entry name.
>+  @param Data            Point to the got heximal UINTN value.
>+
>+  @retval EFI_SUCCESS    Section entry heximal UINTN value is got.
>+  @retval EFI_NOT_FOUND  Section is not found.
>+**/
>+EFI_STATUS
>+EFIAPI
>+GetHexUintnFromDataFile(
>+  IN      VOID                          *Context,
>+  IN      CHAR8                         *SectionName,
>+  IN      CHAR8                         *EntryName,
>+  OUT     UINTN                         *Data
>+  );
>+
>+/**
>+  Get section entry heximal UINT64 value.
>+
>+  @param Context         INI Config file context.
>+  @param SectionName     Section name.
>+  @param EntryName       Section entry name.
>+  @param Data            Point to the got heximal UINT64 value.
>+
>+  @retval EFI_SUCCESS    Section entry heximal UINT64 value is got.
>+  @retval EFI_NOT_FOUND  Section is not found.
>+**/
>+EFI_STATUS
>+EFIAPI
>+GetHexUint64FromDataFile(
>+  IN      VOID                          *Context,
>+  IN      CHAR8                         *SectionName,
>+  IN      CHAR8                         *EntryName,
>+  OUT     UINT64                        *Data
>+  );
>+
>+/**
>+  Close an INI config file and free the context.
>+
>+  @param Context         INI Config file context.
>+**/
>+VOID
>+EFIAPI
>+CloseDataFile(
>+  IN      VOID                          *Context
>+  );
>+
>+#endif
>+
>--
>2.7.4.windows.1
>
>_______________________________________________
>edk2-devel mailing list
>edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>
>https://lists.01.org/mailman/listinfo/edk2-devel


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

* Re: [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application.
  2016-09-29  6:39       ` Ni, Ruiyu
@ 2016-09-29 19:10         ` Carsey, Jaben
  2016-09-30  4:13           ` Ni, Ruiyu
  0 siblings, 1 reply; 83+ messages in thread
From: Carsey, Jaben @ 2016-09-29 19:10 UTC (permalink / raw)
  To: Ni, Ruiyu, Yao, Jiewen, Kinney, Michael D,
	edk2-devel@lists.01.org
  Cc: Tian, Feng, Zhang, Chao B, Gao, Liming, Zeng, Star, Carsey, Jaben

I am confused.

Why is LoadOption and LoadOptionSize not working?  This is specified as part of UEFI Spec (Note: Not UEFI Shell Spec) as a standard way to pass parameters to UEFI appliations.  I think this should work (although it is more work than just examining argc/argv).

-Jaben

From: Ni, Ruiyu
Sent: Wednesday, September 28, 2016 11:40 PM
To: Yao, Jiewen <jiewen.yao@intel.com>; Kinney, Michael D <michael.d.kinney@intel.com>; edk2-devel@lists.01.org
Cc: Tian, Feng <feng.tian@intel.com>; Zhang, Chao B <chao.b.zhang@intel.com>; Gao, Liming <liming.gao@intel.com>; Zeng, Star <star.zeng@intel.com>; Carsey, Jaben <jaben.carsey@intel.com>
Subject: RE: [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application.
Importance: High

Jiewen,
The way CapsuleApp extracts the ARGV assumes UEFI Shell encodes the parameters using a certain way. But the parameter encoding way is not described in the Shell spec.
Maybe we can put the CapsuleApp in ShellPkg, then let it directly use ShellParameter protocol to get the ARGV.

Copying Jaben.

Regards,
Ray

From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of Yao, Jiewen
Sent: Thursday, September 29, 2016 10:37 AM
To: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>; edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>
Cc: Tian, Feng <feng.tian@intel.com<mailto:feng.tian@intel.com>>; Zhang, Chao B <chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com>>; Gao, Liming <liming.gao@intel.com<mailto:liming.gao@intel.com>>; Zeng, Star <star.zeng@intel.com<mailto:star.zeng@intel.com>>
Subject: Re: [edk2] [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application.

Right. CapsuleOnDisk is not supported in BIOS yet.
I will remove it in CapsuleApp.

CapsuleApp just works as an agent to pass capsule to CapsuleDxeRuntime driver.
So it is checked by CapsuleDxeRuntime, not CapsuleApp.

Thank you
Yao Jiewen

From: Kinney, Michael D
Sent: Thursday, September 29, 2016 9:06 AM
To: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>; Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>
Cc: Tian, Feng <feng.tian@intel.com<mailto:feng.tian@intel.com>>; Zeng, Star <star.zeng@intel.com<mailto:star.zeng@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: [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application.

Jiewen,

Does the capsule on disk feature provided by this app work?

I tried it with the QuarkPlatformPkg capsule and I can get
The app to copy the capsule to an EFI System Partition, but
The logic after that point looks incomplete.

Also, if I clear the Persist and Reset flags on the capsule,
the immediate processing of the capsule does not work.

Is there any FW code that will look for capsules on disk?

If there are incomplete features in CapsuleApp, then I think
we should remove them.

Mike

> -----Original Message-----
> From: Yao, Jiewen
> Sent: Tuesday, September 20, 2016 11:45 PM
> To: edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org%3cmailto:edk2-devel@lists.01.org>>
> Cc: Tian, Feng <feng.tian@intel.com<mailto:feng.tian@intel.com<mailto:feng.tian@intel.com%3cmailto:feng.tian@intel.com>>>; Zeng, Star <star.zeng@intel.com<mailto:star.zeng@intel.com<mailto:star.zeng@intel.com%3cmailto:star.zeng@intel.com>>>; Kinney, Michael
> D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com%3cmailto:michael.d.kinney@intel.com>>>; Gao, Liming <liming.gao@intel.com<mailto:liming.gao@intel.com<mailto:liming.gao@intel.com%3cmailto:liming.gao@intel.com>>>; Zhang, Chao B
> <chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com%3cmailto:chao.b.zhang@intel.com>>>
> Subject: [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application.
>
> This CapsuleApp can help perform capsule update in UEFI shell environment.
> It can also dump capsule information, capsule status variable, ESRT and FMP.
>
> Cc: Feng Tian <feng.tian@intel.com<mailto:feng.tian@intel.com<mailto:feng.tian@intel.com%3cmailto:feng.tian@intel.com>>>
> Cc: Star Zeng <star.zeng@intel.com<mailto:star.zeng@intel.com<mailto:star.zeng@intel.com%3cmailto:star.zeng@intel.com>>>
> Cc: Michael D Kinney <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com%3cmailto:michael.d.kinney@intel.com>>>
> Cc: Liming Gao <liming.gao@intel.com<mailto:liming.gao@intel.com<mailto:liming.gao@intel.com%3cmailto:liming.gao@intel.com>>>
> Cc: Chao Zhang <chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com%3cmailto:chao.b.zhang@intel.com>>>
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Jiewen Yao <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com<mailto:jiewen.yao@intel.com%3cmailto:jiewen.yao@intel.com>>>
> ---
>  MdeModulePkg/Application/CapsuleApp/AppSupport.c        |  480 +++++++++
>  MdeModulePkg/Application/CapsuleApp/CapsuleApp.c        | 1047 ++++++++++++++++++++
>  MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf      |   71 ++
>  MdeModulePkg/Application/CapsuleApp/CapsuleApp.uni      |   22 +
>  MdeModulePkg/Application/CapsuleApp/CapsuleAppExtra.uni |   19 +
>  MdeModulePkg/Application/CapsuleApp/CapsuleDump.c       |  840 ++++++++++++++++
>  6 files changed, 2479 insertions(+)
>
> diff --git a/MdeModulePkg/Application/CapsuleApp/AppSupport.c
> b/MdeModulePkg/Application/CapsuleApp/AppSupport.c
> new file mode 100644
> index 0000000..365067d
> --- /dev/null
> +++ b/MdeModulePkg/Application/CapsuleApp/AppSupport.c
> @@ -0,0 +1,480 @@
> +/** @file
> +  A shell application that triggers capsule update process.
> +
> +  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the BSD License
> +  which accompanies this distribution.  The full text of the license may be found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +
> +**/
> +
> +#include <Uefi.h>
> +#include <Library/BaseLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/UefiRuntimeServicesTableLib.h>
> +#include <Library/UefiLib.h>
> +#include <Library/PrintLib.h>
> +#include <Protocol/LoadedImage.h>
> +#include <Protocol/SimpleFileSystem.h>
> +#include <Guid/FileInfo.h>
> +#include <Guid/Gpt.h>
> +
> +#define MAX_ARG_NUM     11
> +
> +UINTN  Argc = 0;
> +CHAR16 *Argv[MAX_ARG_NUM];
> +CHAR16 *ArgBuffer;
> +
> +/**
> +
> +  This function parse application ARG.
> +
> +  @return Status
> +**/
> +EFI_STATUS
> +GetArg (
> +  VOID
> +  )
> +{
> +  UINT8                         *Data;
> +  UINTN                         DataSize;
> +  CHAR16                        *Index;
> +  CHAR16                        *End;
> +  CHAR16                        *DIndex;
> +  EFI_STATUS                    Status;
> +  EFI_LOADED_IMAGE_PROTOCOL     *LoadedImage;
> +
> +  Status = gBS->HandleProtocol (
> +                  gImageHandle,
> +                  &gEfiLoadedImageProtocolGuid,
> +                  (VOID**)&LoadedImage
> +                  );
> +  if (EFI_ERROR(Status)) {
> +    return Status;
> +  }
> +
> +  Data = LoadedImage->LoadOptions;
> +  DataSize = LoadedImage->LoadOptionsSize;
> +
> +  End = (CHAR16*)(UINTN)(Data + DataSize);
> +  Status = gBS->AllocatePool (EfiBootServicesData, DataSize, (VOID **)&ArgBuffer);
> +  ASSERT_EFI_ERROR (Status);
> +  DIndex = ArgBuffer;
> +  Argv[Argc++] = ArgBuffer;
> +  for (Index = (CHAR16*)Data; Index < End; ) {
> +    if (*Index == L' ') {
> +      *DIndex = L'\0';
> +      if (Argc >= MAX_ARG_NUM) {
> +        return EFI_UNSUPPORTED;
> +      }
> +      Argv[Argc++] = (++ DIndex);
> +      while(*Index == L' ') {
> +        Index ++;
> +      }
> +    }
> +    (*(DIndex ++)) = (*(Index ++));
> +  }
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Clear APP ARG.
> +**/
> +VOID
> +CleanArg (
> +  VOID
> +  )
> +{
> +  FreePool (Argv[0]);
> +}
> +
> +/**
> +  Return File System Volume containing this shell application.
> +
> +  @return File System Volume containing this shell application.
> +**/
> +EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *
> +GetMyVol (
> +  VOID
> +  )
> +{
> +  EFI_STATUS                        Status;
> +  EFI_LOADED_IMAGE_PROTOCOL         *LoadedImage;
> +  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Vol;
> +
> +  Status = gBS->HandleProtocol (
> +                  gImageHandle,
> +                  &gEfiLoadedImageProtocolGuid,
> +                  (VOID **)&LoadedImage
> +                  );
> +  ASSERT_EFI_ERROR (Status);
> +
> +  Status = gBS->HandleProtocol (
> +                  LoadedImage->DeviceHandle,
> +                  &gEfiSimpleFileSystemProtocolGuid,
> +                  (VOID **)&Vol
> +                  );
> +  if (!EFI_ERROR (Status)) {
> +    return Vol;
> +  }
> +
> +  return NULL;
> +}
> +
> +/**
> +  Read a file from this volume.
> +
> +  @param Vol             File System Volume
> +  @param FileName        The file to be read.
> +  @param BufferSize      The file buffer size
> +  @param Buffer          The file buffer
> +
> +  @retval EFI_SUCCESS    Read file successfully
> +  @retval EFI_NOT_FOUND  File not found
> +**/
> +EFI_STATUS
> +ReadFileFromVol (
> +  IN  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Vol,
> +  IN  CHAR16                            *FileName,
> +  OUT UINTN                             *BufferSize,
> +  OUT VOID                              **Buffer
> +  )
> +{
> +  EFI_STATUS                        Status;
> +  EFI_FILE_HANDLE                   RootDir;
> +  EFI_FILE_HANDLE                   Handle;
> +  UINTN                             FileInfoSize;
> +  EFI_FILE_INFO                     *FileInfo;
> +  UINTN                             TempBufferSize;
> +  VOID                              *TempBuffer;
> +
> +  //
> +  // Open the root directory
> +  //
> +  Status = Vol->OpenVolume (Vol, &RootDir);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  //
> +  // Open the file
> +  //
> +  Status = RootDir->Open (
> +                      RootDir,
> +                      &Handle,
> +                      FileName,
> +                      EFI_FILE_MODE_READ,
> +                      0
> +                      );
> +  if (EFI_ERROR (Status)) {
> +    RootDir->Close (RootDir);
> +    return Status;
> +  }
> +
> +  RootDir->Close (RootDir);
> +
> +  //
> +  // Get the file information
> +  //
> +  FileInfoSize = sizeof(EFI_FILE_INFO) + 1024;
> +
> +  FileInfo = AllocateZeroPool (FileInfoSize);
> +  if (FileInfo == NULL) {
> +    Handle->Close (Handle);
> +    return Status;
> +  }
> +
> +  Status = Handle->GetInfo (
> +                     Handle,
> +                     &gEfiFileInfoGuid,
> +                     &FileInfoSize,
> +                     FileInfo
> +                     );
> +  if (EFI_ERROR (Status)) {
> +    Handle->Close (Handle);
> +    gBS->FreePool (FileInfo);
> +    return Status;
> +  }
> +
> +  //
> +  // Allocate buffer for the file data. The last CHAR16 is for L'\0'
> +  //
> +  TempBufferSize = (UINTN) FileInfo->FileSize + sizeof(CHAR16);
> +  TempBuffer = AllocateZeroPool (TempBufferSize);
> +  if (TempBuffer == NULL) {
> +    Handle->Close (Handle);
> +    gBS->FreePool (FileInfo);
> +    return Status;
> +  }
> +
> +  gBS->FreePool (FileInfo);
> +
> +  //
> +  // Read the file data to the buffer
> +  //
> +  Status = Handle->Read (
> +                     Handle,
> +                     &TempBufferSize,
> +                     TempBuffer
> +                     );
> +  if (EFI_ERROR (Status)) {
> +    Handle->Close (Handle);
> +    gBS->FreePool (TempBuffer);
> +    return Status;
> +  }
> +
> +  Handle->Close (Handle);
> +
> +  *BufferSize = TempBufferSize;
> +  *Buffer     = TempBuffer;
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Read a file.
> +  If ScanFs is FLASE, it will use this Vol as default Fs.
> +  If ScanFs is TRUE, it will scan all FS and check the file.
> +    If there is only one file match the name, it will be read.
> +    If there is more than one file match the name, it will return Error.
> +
> +  @param ThisVol         File System Volume
> +  @param FileName        The file to be read.
> +  @param BufferSize      The file buffer size
> +  @param Buffer          The file buffer
> +  @param ScanFs          Need Scan all FS
> +
> +  @retval EFI_SUCCESS    Read file successfully
> +  @retval EFI_NOT_FOUND  File not found
> +  @retval EFI_NO_MAPPING There is duplicated files found
> +**/
> +EFI_STATUS
> +ReadFileToBufferEx (
> +  IN OUT EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   **ThisVol,
> +  IN  CHAR16                               *FileName,
> +  OUT UINTN                                *BufferSize,
> +  OUT VOID                                 **Buffer,
> +  IN  BOOLEAN                              ScanFs
> +  )
> +{
> +  EFI_STATUS                        Status;
> +  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Vol;
> +  UINTN                             TempBufferSize;
> +  VOID                              *TempBuffer;
> +  UINTN                             NoHandles;
> +  EFI_HANDLE                        *HandleBuffer;
> +  UINTN                             Index;
> +
> +  //
> +  // Check parameters
> +  //
> +  if ((FileName == NULL) || (Buffer == NULL) || (ThisVol == NULL)) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  //
> +  // not scan fs
> +  //
> +  if (!ScanFs) {
> +    if (*ThisVol == NULL) {
> +      *ThisVol = GetMyVol ();
> +      if (*ThisVol == NULL) {
> +        return EFI_INVALID_PARAMETER;
> +      }
> +    }
> +    //
> +    // Read file directly from Vol
> +    //
> +    return ReadFileFromVol (*ThisVol, FileName, BufferSize, Buffer);
> +  }
> +
> +  //
> +  // need scan fs
> +  //
> +
> +  //
> +  // Get all Vol handle
> +  //
> +  Status = gBS->LocateHandleBuffer (
> +                   ByProtocol,
> +                   &gEfiSimpleFileSystemProtocolGuid,
> +                   NULL,
> +                   &NoHandles,
> +                   &HandleBuffer
> +                   );
> +  if (EFI_ERROR (Status) && (NoHandles == 0)) {
> +    return EFI_NOT_FOUND;
> +  }
> +
> +  //
> +  // Walk through each Vol
> +  //
> +  *ThisVol = NULL;
> +  *BufferSize = 0;
> +  *Buffer     = NULL;
> +  for (Index = 0; Index < NoHandles; Index++) {
> +    Status = gBS->HandleProtocol (
> +                    HandleBuffer[Index],
> +                    &gEfiSimpleFileSystemProtocolGuid,
> +                    (VOID **)&Vol
> +                    );
> +    if (EFI_ERROR(Status)) {
> +      continue;
> +    }
> +
> +    Status = ReadFileFromVol (Vol, FileName, &TempBufferSize, &TempBuffer);
> +    if (!EFI_ERROR (Status)) {
> +      //
> +      // Read file OK, check duplication
> +      //
> +      if (*ThisVol != NULL) {
> +        //
> +        // Find the duplicated file
> +        //
> +        gBS->FreePool (TempBuffer);
> +        gBS->FreePool (*Buffer);
> +        Print (L"Duplicated FileName found!\n");
> +        return EFI_NO_MAPPING;
> +      } else {
> +        //
> +        // Record value
> +        //
> +        *ThisVol = Vol;
> +        *BufferSize = TempBufferSize;
> +        *Buffer     = TempBuffer;
> +      }
> +    }
> +  }
> +
> +  //
> +  // Scan Fs done
> +  //
> +  if (*ThisVol == NULL) {
> +    return EFI_NOT_FOUND;
> +  }
> +
> +  //
> +  // Done
> +  //
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Read a file.
> +
> +  @param FileName        The file to be read.
> +  @param BufferSize      The file buffer size
> +  @param Buffer          The file buffer
> +
> +  @retval EFI_SUCCESS    Read file successfully
> +  @retval EFI_NOT_FOUND  File not found
> +**/
> +EFI_STATUS
> +ReadFileToBuffer (
> +  IN  CHAR16                               *FileName,
> +  OUT UINTN                                *BufferSize,
> +  OUT VOID                                 **Buffer
> +  )
> +{
> +  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Vol;
> +  Vol = NULL;
> +  return ReadFileToBufferEx(&Vol, FileName, BufferSize, Buffer, FALSE);
> +}
> +
> +/**
> +  Write a file.
> +
> +  @param FileName        The file to be written.
> +  @param BufferSize      The file buffer size
> +  @param Buffer          The file buffer
> +
> +  @retval EFI_SUCCESS    Write file successfully
> +**/
> +EFI_STATUS
> +WriteFileFromBuffer(
> +  IN  CHAR16                               *FileName,
> +  IN  UINTN                                BufferSize,
> +  IN  VOID                                 *Buffer
> +  )
> +{
> +  EFI_STATUS                        Status;
> +  EFI_FILE_HANDLE                   RootDir;
> +  EFI_FILE_HANDLE                   Handle;
> +  UINTN                             TempBufferSize;
> +  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Vol;
> +
> +  Vol = GetMyVol();
> +
> +  //
> +  // Open the root directory
> +  //
> +  Status = Vol->OpenVolume (Vol, &RootDir);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  //
> +  // Open the file
> +  //
> +  Status = RootDir->Open (
> +                      RootDir,
> +                      &Handle,
> +                      FileName,
> +                      EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE| EFI_FILE_MODE_CREATE,
> +                      0
> +                      );
> +  if (EFI_ERROR (Status)) {
> +    RootDir->Close (RootDir);
> +    return Status;
> +  }
> +
> +  //
> +  // Delete file
> +  //
> +  Status = Handle->Delete(Handle);
> +  if (EFI_ERROR(Status)) {
> +    return Status;
> +  }
> +
> +  //
> +  // Open the file again
> +  //
> +  Status = RootDir->Open (
> +                      RootDir,
> +                      &Handle,
> +                      FileName,
> +                      EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE| EFI_FILE_MODE_CREATE,
> +                      0
> +                      );
> +  if (EFI_ERROR (Status)) {
> +    RootDir->Close (RootDir);
> +    return Status;
> +  }
> +
> +  RootDir->Close (RootDir);
> +
> +  //
> +  // Write the file data from the buffer
> +  //
> +  TempBufferSize = BufferSize;
> +  Status = Handle->Write (
> +                     Handle,
> +                     &TempBufferSize,
> +                     Buffer
> +                     );
> +  if (EFI_ERROR (Status)) {
> +    Handle->Close (Handle);
> +    return Status;
> +  }
> +
> +  Handle->Close (Handle);
> +
> +  return EFI_SUCCESS;
> +}
> +
> diff --git a/MdeModulePkg/Application/CapsuleApp/CapsuleApp.c
> b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.c
> new file mode 100644
> index 0000000..0a28557
> --- /dev/null
> +++ b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.c
> @@ -0,0 +1,1047 @@
> +/** @file
> +  A shell application that triggers capsule update process.
> +
> +  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the BSD License
> +  which accompanies this distribution.  The full text of the license may be found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +
> +**/
> +
> +#include <Uefi.h>
> +#include <Library/BaseLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/UefiRuntimeServicesTableLib.h>
> +#include <Library/UefiLib.h>
> +#include <Library/PrintLib.h>
> +#include <Protocol/LoadedImage.h>
> +#include <Protocol/SimpleFileSystem.h>
> +#include <Protocol/GraphicsOutput.h>
> +#include <Guid/FileInfo.h>
> +#include <Guid/Gpt.h>
> +#include <Guid/GlobalVariable.h>
> +#include <Guid/CapsuleReport.h>
> +#include <Guid/SystemResourceTable.h>
> +#include <Guid/FmpCapsule.h>
> +#include <IndustryStandard/WindowsUxCapsule.h>
> +
> +#define CAPSULE_HEADER_SIZE  0x20
> +
> +#define NESTED_CAPSULE_HEADER_SIZE  SIZE_4KB
> +#define SYSTEM_FIRMWARE_FLAG 0x50000
> +#define DEVICE_FIRMWARE_FLAG 0x78010
> +
> +#define EFI_CAPSULE_FROM_FILE_DIR                           L"\\EFI\\UpdateCapsule\\<file:///\\EFI\UpdateCapsule\><file:///\\EFI\UpdateCapsule\%3cfile:\EFI\UpdateCapsule\%3e>"
> +#define EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED  0x0000000000000004
> +
> +#define MAJOR_VERSION   1
> +#define MINOR_VERSION   0
> +
> +#define MAX_ARG_NUM     11
> +#define MAX_CAPSULE_NUM (MAX_ARG_NUM - 1)
> +
> +extern UINTN  Argc;
> +extern CHAR16 *Argv[];
> +
> +//
> +// Define how many block descriptors we want to test with.
> +//
> +UINTN  NumberOfDescriptors = 1;
> +UINTN  CapsuleFirstIndex;
> +UINTN  CapsuleLastIndex;
> +
> +/**
> +  Dump capsule information
> +
> +  @retval EFI_SUCCESS            The capsule information is dumped.
> +  @retval EFI_UNSUPPORTED        Input parameter is not valid.
> +**/
> +EFI_STATUS
> +DumpCapsule(
> +  VOID
> +  );
> +
> +/**
> +  Dump capsule status variable.
> +
> +  @retval EFI_SUCCESS            The capsule status variable is dumped.
> +  @retval EFI_UNSUPPORTED        Input parameter is not valid.
> +**/
> +EFI_STATUS
> +DmpCapsuleStatusVariable(
> +  VOID
> +  );
> +
> +/**
> +  Dump FMP protocol info.
> +**/
> +VOID
> +DumpFmpData(
> +  VOID
> +  );
> +
> +/**
> +  Dump ESRT info.
> +**/
> +VOID
> +DumpEsrtData(
> +  VOID
> +  );
> +
> +/**
> +  Read a file.
> +
> +  @param FileName        The file to be read.
> +  @param BufferSize      The file buffer size
> +  @param Buffer          The file buffer
> +
> +  @retval EFI_SUCCESS    Read file successfully
> +  @retval EFI_NOT_FOUND  File not found
> +**/
> +EFI_STATUS
> +ReadFileToBuffer(
> +  IN  CHAR16                               *FileName,
> +  OUT UINTN                                *BufferSize,
> +  OUT VOID                                 **Buffer
> +  );
> +
> +/**
> +  Write a file.
> +
> +  @param FileName        The file to be written.
> +  @param BufferSize      The file buffer size
> +  @param Buffer          The file buffer
> +
> +  @retval EFI_SUCCESS    Write file successfully
> +**/
> +EFI_STATUS
> +WriteFileFromBuffer(
> +  IN  CHAR16                               *FileName,
> +  IN  UINTN                                BufferSize,
> +  IN  VOID                                 *Buffer
> +  );
> +
> +/**
> +
> +  This function parse application ARG.
> +
> +  @return Status
> +**/
> +EFI_STATUS
> +GetArg (
> +  VOID
> +  );
> +
> +/**
> +  Clear APP ARG.
> +**/
> +VOID
> +CleanArg (
> +  VOID
> +  );
> +
> +/**
> +  Create UX capsule.
> +
> +  @retval EFI_SUCCESS            The capsule header is appended.
> +  @retval EFI_UNSUPPORTED        Input parameter is not valid.
> +  @retval EFI_OUT_OF_RESOURCES   No enough resource to create UX capsule.
> +**/
> +EFI_STATUS
> +CreateBmpFmp(
> +  VOID
> +  )
> +{
> +  CHAR16                                        *OutputCapsuleName;
> +  VOID                                          *BmpBuffer;
> +  UINTN                                         FileSize;
> +  CHAR16                                        *BmpName;
> +  UINT8                                         *FullCapsuleBuffer;
> +  UINTN                                         FullCapsuleBufferSize;
> +  EFI_DISPLAY_CAPSULE                           *DisplayCapsule;
> +  EFI_STATUS                                    Status;
> +  EFI_GRAPHICS_OUTPUT_PROTOCOL                  *Gop;
> +
> +  Status = gBS->LocateProtocol(&gEfiGraphicsOutputProtocolGuid, NULL, (VOID **)&Gop);
> +  if (EFI_ERROR(Status)) {
> +    Print(L"CapsuleApp: NO GOP is found.\n");
> +    return EFI_UNSUPPORTED;
> +  }
> +  Print(L"Current GOP: Mode - %d, ", Gop->Mode->Mode);
> +  Print(L"HorizontalResolution - %d, ", Gop->Mode->Info->HorizontalResolution);
> +  Print(L"VerticalResolution - %d\n", Gop->Mode->Info->VerticalResolution);
> +  // HorizontalResolution >= BMP_IMAGE_HEADER.PixelWidth
> +  // VerticalResolution   >= BMP_IMAGE_HEADER.PixelHeight
> +
> +  if (Argc != 5) {
> +    Print(L"CapsuleApp: Invalid Parameter.\n");
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  if (StrCmp(Argv[3], L"-O") != 0) {
> +    Print(L"CapsuleApp: NO output capsule name.\n");
> +    return EFI_UNSUPPORTED;
> +  }
> +  OutputCapsuleName = Argv[4];
> +
> +  BmpBuffer = NULL;
> +  FileSize = 0;
> +  FullCapsuleBuffer = NULL;
> +
> +  BmpName = Argv[2];
> +  Status = ReadFileToBuffer(BmpName, &FileSize, &BmpBuffer);
> +  if (EFI_ERROR(Status)) {
> +    Print(L"CapsuleApp: BMP image (%s) is not found.\n", BmpName);
> +    goto Done;
> +  }
> +
> +  FullCapsuleBufferSize = sizeof(EFI_DISPLAY_CAPSULE) + FileSize;
> +  FullCapsuleBuffer = AllocatePool(FullCapsuleBufferSize);
> +  if (FullCapsuleBuffer == NULL) {
> +    Print(L"CapsuleApp: Capsule Buffer size (0x%x) too big.\n",
> FullCapsuleBufferSize);
> +    Status = EFI_OUT_OF_RESOURCES;
> +    goto Done;
> +  }
> +
> +  DisplayCapsule = (EFI_DISPLAY_CAPSULE *)FullCapsuleBuffer;
> +  CopyGuid(&DisplayCapsule->CapsuleHeader.CapsuleGuid, &gWindowsUxCapsuleGuid);
> +  DisplayCapsule->CapsuleHeader.HeaderSize = sizeof(DisplayCapsule->CapsuleHeader);
> +  DisplayCapsule->CapsuleHeader.Flags = CAPSULE_FLAGS_PERSIST_ACROSS_RESET;
> +  DisplayCapsule->CapsuleHeader.CapsuleImageSize = (UINT32)FullCapsuleBufferSize;
> +
> +  DisplayCapsule->ImagePayload.Version = 1;
> +  DisplayCapsule->ImagePayload.Checksum = 0;
> +  DisplayCapsule->ImagePayload.ImageType = 0; // BMP
> +  DisplayCapsule->ImagePayload.Reserved = 0;
> +  DisplayCapsule->ImagePayload.Mode = Gop->Mode->Mode;
> +  DisplayCapsule->ImagePayload.OffsetX = 0;
> +  DisplayCapsule->ImagePayload.OffsetY = 0;
> +
> +  CopyMem((DisplayCapsule + 1), BmpBuffer, FileSize);
> +
> +  DisplayCapsule->ImagePayload.Checksum = CalculateCheckSum8(FullCapsuleBuffer,
> FullCapsuleBufferSize);
> +
> +  Status = WriteFileFromBuffer(OutputCapsuleName, FullCapsuleBufferSize,
> FullCapsuleBuffer);
> +  Print(L"CapsuleApp: Write %s %r\n", OutputCapsuleName, Status);
> +
> +Done:
> +  if (BmpBuffer != NULL) {
> +    FreePool(BmpBuffer);
> +  }
> +
> +  if (FullCapsuleBuffer != NULL) {
> +    FreePool(FullCapsuleBuffer);
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  Get ImageTypeId in the FMP capsule header.
> +
> +  @param CapsuleHeader  The FMP capsule image header.
> +
> +  @return ImageTypeId
> +**/
> +EFI_GUID *
> +GetCapsuleImageTypeId(
> +  IN EFI_CAPSULE_HEADER                            *CapsuleHeader
> +  )
> +{
> +  EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER       *FmpCapsuleHeader;
> +  UINT64                                       *ItemOffsetList;
> +  EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader;
> +
> +  FmpCapsuleHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *)((UINT8 *)CapsuleHeader
> + CapsuleHeader->HeaderSize);
> +  ItemOffsetList = (UINT64 *)(FmpCapsuleHeader + 1);
> +  if (FmpCapsuleHeader->PayloadItemCount == 0) {
> +    return NULL;
> +  }
> +  ImageHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *)((UINT8
> *)FmpCapsuleHeader + ItemOffsetList[FmpCapsuleHeader->EmbeddedDriverCount]);
> +  return &ImageHeader->UpdateImageTypeId;
> +}
> +
> +/**
> +  Get ESRT FwType according to ImageTypeId
> +
> +  @param  ImageTypeId   ImageTypeId of an FMP capsule.
> +
> +  @return ESRT FwType
> +**/
> +UINT32
> +GetEsrtFwType(
> +  IN  EFI_GUID                                      *ImageTypeId
> +  )
> +{
> +  EFI_STATUS                 Status;
> +  EFI_SYSTEM_RESOURCE_TABLE  *Esrt;
> +  EFI_SYSTEM_RESOURCE_ENTRY  *EsrtEntry;
> +  UINTN                      Index;
> +
> +  //
> +  // Check ESRT
> +  //
> +  Status = EfiGetSystemConfigurationTable(&gEfiSystemResourceTableGuid, (VOID
> **)&Esrt);
> +  if (!EFI_ERROR(Status)) {
> +    EsrtEntry = (VOID *)(Esrt + 1);
> +    for (Index = 0; Index < Esrt->FwResourceCount; Index++, EsrtEntry++) {
> +      if (CompareGuid(&EsrtEntry->FwClass, ImageTypeId)) {
> +        return EsrtEntry->FwType;
> +      }
> +    }
> +  }
> +
> +  return ESRT_FW_TYPE_UNKNOWN;
> +}
> +
> +/**
> +  Append a capsule header on top of current image.
> +  This function follows Windows UEFI Firmware Update Platform document.
> +
> +  @retval EFI_SUCCESS            The capsule header is appended.
> +  @retval EFI_UNSUPPORTED        Input parameter is not valid.
> +  @retval EFI_OUT_OF_RESOURCES   No enough resource to append capsule header.
> +**/
> +EFI_STATUS
> +CreateNestedFmp(
> +  VOID
> +  )
> +{
> +  CHAR16                                        *OutputCapsuleName;
> +  VOID                                          *CapsuleBuffer;
> +  UINTN                                         FileSize;
> +  CHAR16                                        *CapsuleName;
> +  UINT8                                         *FullCapsuleBuffer;
> +  UINTN                                         FullCapsuleBufferSize;
> +  EFI_CAPSULE_HEADER                            *NestedCapsuleHeader;
> +  EFI_GUID                                      *ImageTypeId;
> +  UINT32                                        FwType;
> +  EFI_STATUS                                    Status;
> +
> +  if (Argc != 5) {
> +    Print(L"CapsuleApp: Invalid Parameter.\n");
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  if (StrCmp(Argv[3], L"-O") != 0) {
> +    Print(L"CapsuleApp: NO output capsule name.\n");
> +    return EFI_UNSUPPORTED;
> +  }
> +  OutputCapsuleName = Argv[4];
> +
> +  CapsuleBuffer = NULL;
> +  FileSize = 0;
> +  FullCapsuleBuffer = NULL;
> +
> +  CapsuleName = Argv[2];
> +  Status = ReadFileToBuffer(CapsuleName, &FileSize, &CapsuleBuffer);
> +  if (EFI_ERROR(Status)) {
> +    Print(L"CapsuleApp: Capsule image (%s) is not found.\n", CapsuleName);
> +    goto Done;
> +  }
> +
> +  ImageTypeId = GetCapsuleImageTypeId(CapsuleBuffer);
> +  if (ImageTypeId == NULL) {
> +    Print(L"CapsuleApp: Capsule ImageTypeId is not found.\n");
> +    goto Done;
> +  }
> +  FwType = GetEsrtFwType(ImageTypeId);
> +  if ((FwType != ESRT_FW_TYPE_SYSTEMFIRMWARE) && (FwType !=
> ESRT_FW_TYPE_DEVICEFIRMWARE)) {
> +    Print(L"CapsuleApp: Capsule FwType is invalid.\n");
> +    goto Done;
> +  }
> +
> +  FullCapsuleBufferSize = NESTED_CAPSULE_HEADER_SIZE + FileSize;
> +  FullCapsuleBuffer = AllocatePool(FullCapsuleBufferSize);
> +  if (FullCapsuleBuffer == NULL) {
> +    Print(L"CapsuleApp: Capsule Buffer size (0x%x) too big.\n",
> FullCapsuleBufferSize);
> +    Status = EFI_OUT_OF_RESOURCES;
> +    goto Done;
> +  }
> +
> +  NestedCapsuleHeader = (EFI_CAPSULE_HEADER *)FullCapsuleBuffer;
> +  ZeroMem(NestedCapsuleHeader, NESTED_CAPSULE_HEADER_SIZE);
> +  CopyGuid(&NestedCapsuleHeader->CapsuleGuid, ImageTypeId);
> +  NestedCapsuleHeader->HeaderSize = NESTED_CAPSULE_HEADER_SIZE;
> +  NestedCapsuleHeader->Flags = (FwType == ESRT_FW_TYPE_DEVICEFIRMWARE) ?
> SYSTEM_FIRMWARE_FLAG : DEVICE_FIRMWARE_FLAG;
> +  NestedCapsuleHeader->CapsuleImageSize = (UINT32)FullCapsuleBufferSize;
> +
> +  CopyMem((UINT8 *)NestedCapsuleHeader + NestedCapsuleHeader->HeaderSize,
> CapsuleBuffer, FileSize);
> +
> +  Status = WriteFileFromBuffer(OutputCapsuleName, FullCapsuleBufferSize,
> FullCapsuleBuffer);
> +  Print(L"CapsuleApp: Write %s %r\n", OutputCapsuleName, Status);
> +
> +Done:
> +  if (CapsuleBuffer != NULL) {
> +    FreePool(CapsuleBuffer);
> +  }
> +
> +  if (FullCapsuleBuffer != NULL) {
> +    FreePool(FullCapsuleBuffer);
> +  }
> +
> +  return Status;
> +}
> +
> +
> +/**
> +  Clear capsule status variable.
> +
> +  @retval EFI_SUCCESS            The capsule status variable is cleared.
> +**/
> +EFI_STATUS
> +ClearCapsuleStatusVariable(
> +  VOID
> +  )
> +{
> +  EFI_STATUS                          Status;
> +  UINT32                              Index;
> +  CHAR16                              CapsuleVarName[20];
> +  CHAR16                              *TempVarName;
> +
> +  StrCpyS (CapsuleVarName, sizeof(CapsuleVarName)/sizeof(CapsuleVarName[0]),
> L"Capsule");
> +  TempVarName = CapsuleVarName + StrLen (CapsuleVarName);
> +  Index = 0;
> +
> +  while (TRUE) {
> +    UnicodeSPrint (TempVarName, 5 * sizeof(CHAR16), L"%04x", Index);
> +
> +    Status = gRT->SetVariable (
> +                    CapsuleVarName,
> +                    &gEfiCapsuleReportGuid,
> +                    EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS |
> EFI_VARIABLE_BOOTSERVICE_ACCESS,
> +                    0,
> +                    (VOID *)NULL
> +                    );
> +    if (EFI_ERROR(Status)) {
> +      //
> +      // There is no capsule variables, quit
> +      //
> +      break;
> +    }
> +
> +    Index++;
> +    if (Index > 0xFFFF) {
> +      break;
> +    }
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Get the active UEFI system partition from bootoption list.
> +
> +  @param[out] Fs    Simple File System protocol on the active UEFI system partition
> +
> +  @retval EFI_SUCCESS   active UEFI system partition found
> +**/
> +EFI_STATUS
> +GetEfiSysPartition(
> +  OUT EFI_SIMPLE_FILE_SYSTEM_PROTOCOL **Fs
> +  )
> +{
> +  EFI_STATUS                       Status;
> +  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL  *FsTemp;
> +  UINTN                            NoHandles;
> +  EFI_HANDLE                       *Handles;
> +  UINTN                            Index;
> +
> +  Handles = NULL;
> +
> +  //
> +  // search for EFI system partition protocol on Boot option device path
> +  //
> +  Status = gBS->LocateHandleBuffer(ByProtocol, &gEfiPartTypeSystemPartGuid, NULL,
> &NoHandles, &Handles);
> +  if (EFI_ERROR(Status)) {
> +    return Status;
> +  }
> +
> +  //
> +  // Skip BootOptions within FV
> +  //
> +  for (Index = 0; Index < NoHandles; Index++) {
> +    Status = gBS->HandleProtocol (Handles[Index], &gEfiSimpleFileSystemProtocolGuid,
> (VOID **)&FsTemp);
> +    if (!EFI_ERROR (Status)){
> +      *Fs = FsTemp;
> +      break;
> +    }
> +  }
> +  return Status;
> +}
> +
> +/**
> +  Copy a list of capsule images to the active UEFI system partition from bootoption
> list.
> +
> +  @param[in] CapsuleBuffer    An array of pointer to capsule images
> +  @param[in] FileSize         An array of UINTN to capsule images size
> +  @param[in] CapsuleNum       The count of capsule images
> +
> +  @retval EFI_SUCCESS   Capsule images are copied to the active UEFI system partition
> +**/
> +EFI_STATUS
> +CopyCapsuleToActiveEfiPartition(
> +  IN VOID                          **CapsuleBuffer,
> +  IN UINTN                         *FileSize,
> +  IN UINTN                         CapsuleNum
> +  )
> +{
> +  EFI_STATUS                       Status;
> +  CHAR16                           *CapsuleName;
> +  UINTN                            Index;
> +  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL  *Fs;
> +  EFI_FILE_HANDLE                  RootDir;
> +  EFI_FILE_HANDLE                  CapsuleDir;
> +  EFI_FILE_HANDLE                  DestHandle;
> +  UINTN                            DataSize;
> +  UINT64                           OsIndication;
> +
> +  RootDir      = NULL;
> +  CapsuleDir   = NULL;
> +
> +  Status = GetEfiSysPartition(&Fs);
> +  if (EFI_ERROR(Status)) {
> +    Print (L"Can not find active UEFI System Partition\n");
> +    return Status;
> +  }
> +
> +  Status = Fs->OpenVolume(Fs, &RootDir);
> +  if (EFI_ERROR(Status)) {
> +    goto EXIT;
> +  }
> +
> +  Status = RootDir->Open(
> +                      RootDir,
> +                      &CapsuleDir,
> +                      EFI_CAPSULE_FROM_FILE_DIR,
> +                      EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE,
> +                      EFI_FILE_DIRECTORY
> +                      );
> +  if (EFI_ERROR(Status)) {
> +    goto EXIT;
> +  }
> +
> +  //
> +  // Read the input files.
> +  //
> +  for (Index = 0; Index < CapsuleNum; Index++) {
> +    CapsuleName = Argv[CapsuleFirstIndex + Index];
> +    Status = CapsuleDir->Open(
> +                           CapsuleDir,
> +                           &DestHandle,
> +                           CapsuleName,
> +                           EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE |
> EFI_FILE_MODE_CREATE,
> +                           EFI_FILE_ARCHIVE
> +                           );
> +    if (EFI_ERROR(Status)) {
> +      Print(L"CapsuleApp: %s open error - %r\n", CapsuleName, Status);
> +      continue;
> +    }
> +
> +    DataSize = FileSize[Index];
> +    Status = DestHandle->Write(
> +                           DestHandle,
> +                           &DataSize,
> +                           CapsuleBuffer[Index]
> +                           );
> +    DestHandle->Close(DestHandle);
> +    if (EFI_ERROR(Status)) {
> +      Print(L"CapsuleApp: %s write error - %r, FileSize - 0x%x\n", CapsuleName,
> Status, FileSize[Index]);
> +    }
> +  }
> +
> +  Status = gRT->GetVariable (
> +                  L"OsIndications",
> +                  &gEfiGlobalVariableGuid,
> +                  NULL,
> +                  &DataSize,
> +                  (VOID *) &OsIndication
> +                  );
> +
> +  if (EFI_ERROR(Status) || DataSize != sizeof(OsIndication)) {
> +    OsIndication = 0;
> +  }
> +
> +  //
> +  // Set OsIndications Variable EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED bit
> +  //
> +  OsIndication |= EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED;
> +  Status = gRT->SetVariable (
> +                  L"OsIndications",
> +                  &gEfiGlobalVariableGuid,
> +                  EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS |
> +                  EFI_VARIABLE_BOOTSERVICE_ACCESS,
> +                  sizeof(OsIndication),
> +                  (VOID *)&OsIndication
> +                  );
> +
> +
> +EXIT:
> +  if (RootDir != NULL) {
> +    RootDir->Close(RootDir);
> +  }
> +
> +  if (CapsuleDir != NULL) {
> +    CapsuleDir->Close(CapsuleDir);
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  Build Gather list for a list of capsule images.
> +
> +  @param[in]  CapsuleBuffer    An array of pointer to capsule images
> +  @param[in]  FileSize         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                         *FileSize,
> +  IN UINTN                         CapsuleNum,
> +  OUT EFI_CAPSULE_BLOCK_DESCRIPTOR **BlockDescriptors
> +  )
> +{
> +  EFI_STATUS                    Status;
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR  *BlockDescriptors1;
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR  *BlockDescriptors2;
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR  *BlockDescriptorPre;
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR  *BlockDescriptorsHeader;
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR  *TempBlockPtr;
> +  UINT8                         *TempDataPtr;
> +  UINTN                         SizeLeft;
> +  UINTN                         Size;
> +  INT32                         Count;
> +  INT32                         Number;
> +  UINTN                         Index;
> +
> +  TempBlockPtr           = NULL;
> +  BlockDescriptors1      = NULL;
> +  BlockDescriptors2      = NULL;
> +  BlockDescriptorPre     = NULL;
> +  BlockDescriptorsHeader = NULL;
> +
> +  for (Index = 0; Index < CapsuleNum; Index++) {
> +    //
> +    // Allocate memory for the descriptors.
> +    //
> +    if (NumberOfDescriptors == 1) {
> +      Count = 2;
> +    } else {
> +      Count = (INT32)(NumberOfDescriptors + 2) / 2;
> +    }
> +
> +    Size               = Count * sizeof (EFI_CAPSULE_BLOCK_DESCRIPTOR);
> +    BlockDescriptors1  = AllocateRuntimeZeroPool (Size);
> +    if (BlockDescriptors1 == NULL) {
> +      Print (L"CapsuleApp: failed to allocate memory for descriptors\n");
> +      Status = EFI_OUT_OF_RESOURCES;
> +      goto ERREXIT;
> +    } else {
> +      Print (L"CapsuleApp: creating capsule descriptors at 0x%X\n", (UINTN)
> BlockDescriptors1);
> +      Print (L"CapsuleApp: capsule data starts          at 0x%X with size 0x%X\n",
> (UINTN) CapsuleBuffer, FileSize);
> +    }
> +
> +    //
> +    // Record descirptor header
> +    //
> +    if (Index == 0) {
> +      BlockDescriptorsHeader = BlockDescriptors1;
> +    }
> +
> +    if (BlockDescriptorPre != NULL) {
> +      BlockDescriptorPre->Union.ContinuationPointer = (UINTN) BlockDescriptors1;
> +      BlockDescriptorPre->Length = 0;
> +    }
> +
> +    //
> +    // Fill them in
> +    //
> +    TempBlockPtr  = BlockDescriptors1;
> +    TempDataPtr   = CapsuleBuffer[Index];
> +    SizeLeft      = FileSize[Index];
> +    for (Number = 0; (Number < Count - 1) && (SizeLeft != 0); Number++) {
> +      //
> +      // Divide remaining data in half
> +      //
> +      if (NumberOfDescriptors != 1) {
> +        if (SizeLeft == 1) {
> +          Size = 1;
> +        } else {
> +          Size = SizeLeft / 2;
> +        }
> +      } else {
> +        Size = SizeLeft;
> +      }
> +      TempBlockPtr->Union.DataBlock    = (UINTN)TempDataPtr;
> +      TempBlockPtr->Length  = Size;
> +      Print (L"CapsuleApp: capsule block/size              0x%X/0x%X\n", (UINTN)
> TempDataPtr, Size);
> +      SizeLeft -= Size;
> +      TempDataPtr += Size;
> +      TempBlockPtr++;
> +    }
> +
> +    //
> +    // Allocate the second list, point the first block's last entry to point
> +    // to this one, and fill this one in. Worst case is that the previous
> +    // list only had one element that pointed here, so we need at least two
> +    // elements -- one to point to all the data, another to terminate the list.
> +    //
> +    if ((NumberOfDescriptors != 1) && (SizeLeft != 0)) {
> +      Count = (INT32)(NumberOfDescriptors + 2) - Count;
> +      if (Count == 1) {
> +        Count++;
> +      }
> +
> +      Size              = Count * sizeof (EFI_CAPSULE_BLOCK_DESCRIPTOR);
> +      BlockDescriptors2 = AllocateRuntimeZeroPool (Size);
> +      if (BlockDescriptors2 == NULL) {
> +        Print (L"CapsuleApp: failed to allocate memory for descriptors\n");
> +        Status = EFI_OUT_OF_RESOURCES;
> +        goto ERREXIT;
> +      }
> +
> +      //
> +      // Point the first list's last element to point to this second list.
> +      //
> +      TempBlockPtr->Union.ContinuationPointer   = (UINTN) BlockDescriptors2;
> +
> +      TempBlockPtr->Length  = 0;
> +      TempBlockPtr = BlockDescriptors2;
> +      for (Number = 0; Number < Count - 1; Number++) {
> +        //
> +        // If second-to-last one, then dump rest to this element
> +        //
> +        if (Number == (Count - 2)) {
> +          Size = SizeLeft;
> +        } else {
> +          //
> +          // Divide remaining data in half
> +          //
> +          if (SizeLeft == 1) {
> +            Size = 1;
> +          } else {
> +            Size = SizeLeft / 2;
> +          }
> +        }
> +
> +        TempBlockPtr->Union.DataBlock    = (UINTN)TempDataPtr;
> +        TempBlockPtr->Length  = Size;
> +        Print (L"CapsuleApp: capsule block/size              0x%X/0x%X\n", (UINTN)
> TempDataPtr, Size);
> +        SizeLeft -= Size;
> +        TempDataPtr += Size;
> +        TempBlockPtr++;
> +        if (SizeLeft == 0) {
> +          break;
> +        }
> +      }
> +    }
> +
> +    BlockDescriptorPre = TempBlockPtr;
> +    BlockDescriptors1  = NULL;
> +  }
> +
> +  //
> +  // Null-terminate.
> +  //
> +  if (TempBlockPtr != NULL) {
> +    TempBlockPtr->Union.ContinuationPointer    = (UINTN)NULL;
> +    TempBlockPtr->Length  = 0;
> +    *BlockDescriptors = BlockDescriptorsHeader;
> +  }
> +
> +  return EFI_SUCCESS;
> +
> +ERREXIT:
> +  if (BlockDescriptors1 != NULL) {
> +    FreePool(BlockDescriptors1);
> +  }
> +
> +  if (BlockDescriptors2 != NULL) {
> +    FreePool(BlockDescriptors2);
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  Clear the Gather list for a list of capsule images.
> +
> +  @param[in]  BlockDescriptors The block descriptors for the capsule images
> +  @param[in]  CapsuleNum       The count of capsule images
> +**/
> +VOID
> +CleanGatherList(
> +  IN EFI_CAPSULE_BLOCK_DESCRIPTOR   *BlockDescriptors,
> +  IN UINTN                          CapsuleNum
> +  )
> +{
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR   *TempBlockPtr;
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR   *TempBlockPtr1;
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR   *TempBlockPtr2;
> +  UINTN                          Index;
> +
> +  if (BlockDescriptors != NULL) {
> +    TempBlockPtr1 = BlockDescriptors;
> +    while (1){
> +      TempBlockPtr = TempBlockPtr1;
> +      for (Index = 0; Index < CapsuleNum; Index++) {
> +        if (TempBlockPtr[Index].Length == 0) {
> +          break;
> +        }
> +      }
> +
> +      if (TempBlockPtr[Index].Union.ContinuationPointer == (UINTN)NULL) {
> +        break;
> +      }
> +
> +      TempBlockPtr2 = (VOID *) ((UINTN) TempBlockPtr->Union.ContinuationPointer);
> +      FreePool(TempBlockPtr1);
> +      TempBlockPtr1 = TempBlockPtr2;
> +    }
> +  }
> +}
> +
> +/**
> +  Print APP usage.
> +**/
> +VOID
> +PrintUsage (
> +  VOID
> +  )
> +{
> +  Print(L"CapsuleApp:  usage\n");
> +  Print(L"  CapsuleApp [-F] <Capsule...> [-NR]\n");
> +  Print(L"  CapsuleApp -S\n");
> +  Print(L"  CapsuleApp -C\n");
> +  Print(L"  CapsuleApp -P\n");
> +  Print(L"  CapsuleApp -E\n");
> +  Print(L"  CapsuleApp -G <BMP> -O <Capsule>\n");
> +  Print(L"  CapsuleApp -N <Capsule> -O <NestedCapsule>\n");
> +  Print(L"  CapsuleApp -D|-DS <Capsule>\n");
> +  Print(L"Parameter:\n");
> +  Print(L"  -F:  Put capsule file to disk.\n");
> +  Print(L"       No -F means to put capsule file in memory.\n");
> +  Print(L"  -NR: No Reset.\n");
> +  Print(L"  -S:  Dump capsule status.\n");
> +  Print(L"  -C:  Clear capsule status.\n");
> +  Print(L"  -P:  Dump FMP protocol info.\n");
> +  Print(L"  -E:  Dump ESRT table info.\n");
> +  Print(L"  -G:  Input BMP file name\n");
> +  Print(L"  -N:  Append Capsule Header accroding to Windows Firmware Update\n");
> +  Print(L"  -O:  Output Capsule file name\n");
> +  Print(L"  -D:  Dump Capsule\n");
> +  Print(L"  -DS: Dump Capsule with System FMP format\n");
> +}
> +
> +/**
> +  Update Capsule image.
> +
> +  @param[in]  ImageHandle     The image handle.
> +  @param[in]  SystemTable     The system table.
> +
> +  @retval EFI_SUCCESS            Command completed successfully.
> +  @retval EFI_INVALID_PARAMETER  Command usage error.
> +  @retval EFI_NOT_FOUND          The input file can't be found.
> +**/
> +EFI_STATUS
> +EFIAPI
> +UefiMain (
> +  IN EFI_HANDLE        ImageHandle,
> +  IN EFI_SYSTEM_TABLE  *SystemTable
> +  )
> +{
> +  EFI_STATUS                    Status;
> +  UINTN                         FileSize[MAX_CAPSULE_NUM];
> +  VOID                          *CapsuleBuffer[MAX_CAPSULE_NUM];
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR  *BlockDescriptors;
> +  EFI_CAPSULE_HEADER             *CapsuleHeaderArray[MAX_CAPSULE_NUM + 1];
> +  UINT64                         MaxCapsuleSize;
> +  EFI_RESET_TYPE                 ResetType;
> +  BOOLEAN                        NeedReset;
> +  BOOLEAN                        NoReset;
> +  BOOLEAN                        NeedCopyOnDisk;
> +  CHAR16                         *CapsuleName;
> +  UINTN                          CapsuleNum;
> +  UINTN                          Index;
> +
> +  Status = GetArg();
> +  if (EFI_ERROR(Status)) {
> +    PrintUsage();
> +    return Status;
> +  }
> +  if (Argc < 2) {
> +    PrintUsage();
> +    CleanArg();
> +    return EFI_INVALID_PARAMETER;
> +  }
> +  if ((StrCmp(Argv[1], L"-D") == 0) ||
> +      (StrCmp(Argv[1], L"-DS") == 0)) {
> +    Status = DumpCapsule();
> +    CleanArg();
> +    return Status;
> +  }
> +  if (StrCmp(Argv[1], L"-G") == 0) {
> +    Status = CreateBmpFmp();
> +    CleanArg();
> +    return Status;
> +  }
> +  if (StrCmp(Argv[1], L"-N") == 0) {
> +    Status = CreateNestedFmp();
> +    CleanArg();
> +    return Status;
> +  }
> +  if (StrCmp(Argv[1], L"-S") == 0) {
> +    Status = DmpCapsuleStatusVariable();
> +    CleanArg();
> +    return EFI_SUCCESS;
> +  }
> +  if (StrCmp(Argv[1], L"-C") == 0) {
> +    Status = ClearCapsuleStatusVariable();
> +    CleanArg();
> +    return Status;
> +  }
> +  if (StrCmp(Argv[1], L"-P") == 0) {
> +    DumpFmpData();
> +    CleanArg();
> +    return EFI_SUCCESS;
> +  }
> +  if (StrCmp(Argv[1], L"-E") == 0) {
> +    DumpEsrtData();
> +    CleanArg();
> +    return EFI_SUCCESS;
> +  }
> +  if (StrCmp(Argv[1], L"-F") == 0) {
> +    NeedCopyOnDisk = TRUE;
> +    CapsuleFirstIndex = 2;
> +  } else {
> +    NeedCopyOnDisk = FALSE;
> +    CapsuleFirstIndex = 1;
> +  }
> +  if (StrCmp(Argv[Argc - 1], L"-NR") == 0) {
> +    NoReset = TRUE;
> +    CapsuleLastIndex = Argc - 2;
> +  } else {
> +    NoReset = FALSE;
> +    CapsuleLastIndex = Argc - 1;
> +  }
> +  CapsuleNum = CapsuleLastIndex - CapsuleFirstIndex + 1;
> +
> +  if (CapsuleFirstIndex > CapsuleLastIndex) {
> +    Print(L"CapsuleApp: NO capsule image.\n");
> +    CleanArg();
> +    return EFI_UNSUPPORTED;
> +  }
> +  if (CapsuleNum > MAX_CAPSULE_NUM) {
> +    Print(L"CapsuleApp: Too many capsule images.\n");
> +    CleanArg();
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  ZeroMem(&CapsuleBuffer, sizeof(CapsuleBuffer));
> +  ZeroMem(&FileSize, sizeof(FileSize));
> +  BlockDescriptors = NULL;
> +
> +  for (Index = 0; Index < CapsuleNum; Index++) {
> +    CapsuleName = Argv[CapsuleFirstIndex + Index];
> +    Status = ReadFileToBuffer(CapsuleName, &FileSize[Index], &CapsuleBuffer[Index]);
> +    if (EFI_ERROR(Status)) {
> +      Print(L"CapsuleApp: capsule image (%s) is not found.\n", CapsuleName);
> +      goto Done;
> +    }
> +  }
> +
> +  if (NeedCopyOnDisk) {
> +    Status = CopyCapsuleToActiveEfiPartition(CapsuleBuffer, FileSize, CapsuleNum);
> +  } else {
> +    //
> +    // Every capsule use 2 descriptor 1 for data 1 for end
> +    //
> +    Status = BuildGatherList(CapsuleBuffer, FileSize, CapsuleNum, &BlockDescriptors);
> +  }
> +  if (EFI_ERROR(Status)) {
> +    goto Done;
> +  }
> +
> +  //
> +  // Call the runtime service capsule.
> +  //
> +  NeedReset = FALSE;
> +  for (Index = 0; Index < CapsuleNum; Index++) {
> +    CapsuleHeaderArray[Index] = (EFI_CAPSULE_HEADER *) CapsuleBuffer[Index];
> +    if ((CapsuleHeaderArray[Index]->Flags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET) != 0)
> {
> +      NeedReset = TRUE;
> +    }
> +  }
> +  CapsuleHeaderArray[CapsuleNum] = NULL;
> +  if (NoReset) {
> +    NeedReset = FALSE;
> +  }
> +
> +  //
> +  // Inquire platform capability of UpdateCapsule.
> +  //
> +  Status = gRT->QueryCapsuleCapabilities (CapsuleHeaderArray, CapsuleNum,
> &MaxCapsuleSize, &ResetType);
> +  if (EFI_ERROR(Status)) {
> +    Print (L"CapsuleApp: failed to query capsule capability - %r\n", Status);
> +    goto Done;
> +  }
> +
> +  for (Index = 0; Index < CapsuleNum; Index++) {
> +    if (FileSize[Index] > MaxCapsuleSize) {
> +      Print (L"CapsuleApp: capsule is too large to update, %ld is allowed\n",
> MaxCapsuleSize);
> +      Status = EFI_UNSUPPORTED;
> +      goto Done;
> +    }
> +  }
> +
> +  //
> +  // Check whether the input capsule image has the flag of persist across system
> reset.
> +  //
> +  if (NeedReset) {
> +    Status = gRT->UpdateCapsule(CapsuleHeaderArray,CapsuleNum,(UINTN)
> BlockDescriptors);
> +    if (Status != EFI_SUCCESS) {
> +      Print (L"CapsuleApp: failed to update capsule - %r\n", Status);
> +      goto Done;
> +    }
> +    //
> +    // For capsule who has reset flag, after calling UpdateCapsule service,triger a
> +    // system reset to process capsule persist across a system reset.
> +    //
> +    gRT->ResetSystem (ResetType, EFI_SUCCESS, 0, NULL);
> +  } else {
> +    //
> +    // For capsule who has no reset flag, only call UpdateCapsule Service without a
> +    // system reset. The service will process the capsule immediately.
> +    //
> +    Status = gRT->UpdateCapsule (CapsuleHeaderArray,CapsuleNum,(UINTN)
> BlockDescriptors);
> +    if (Status != EFI_SUCCESS) {
> +      Print (L"CapsuleApp: failed to update capsule - %r\n", Status);
> +    }
> +  }
> +
> +  Status = EFI_SUCCESS;
> +
> +Done:
> +  for (Index = 0; Index < CapsuleNum; Index++) {
> +    if (CapsuleBuffer[Index] != NULL) {
> +      FreePool (CapsuleBuffer[Index]);
> +    }
> +  }
> +
> +  CleanGatherList(BlockDescriptors, CapsuleNum);
> +  CleanArg();
> +
> +  return Status;
> +}
> diff --git a/MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf
> b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf
> new file mode 100644
> index 0000000..7ee44fc
> --- /dev/null
> +++ b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf
> @@ -0,0 +1,71 @@
> +##  @file
> +#  A shell application that triggers capsule update process.
> +#
> +# This application can trigger capsule update process. It can also
> +# generate capsule image, or dump capsule variable information.
> +#
> +#  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
> +#  This program and the accompanying materials
> +#  are licensed and made available under the terms and conditions of the BSD License
> +#  which accompanies this distribution.  The full text of the license may be found at
> +#  http://opensource.org/licenses/bsd-license.php
> +#
> +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +#
> +##
> +
> +[Defines]
> +  INF_VERSION                    = 0x00010006
> +  BASE_NAME                      = CapsuleApp
> +  MODULE_UNI_FILE                = CapsuleApp.uni
> +  FILE_GUID                      = 4CEF31DA-8682-4274-9CC4-AEE7516A5E7B
> +  MODULE_TYPE                    = UEFI_APPLICATION
> +  VERSION_STRING                 = 1.0
> +  ENTRY_POINT                    = UefiMain
> +
> +#
> +# The following information is for reference only and not required by the build tools.
> +#
> +#  VALID_ARCHITECTURES           = IA32 X64
> +#
> +
> +[Sources]
> +  CapsuleApp.c
> +  CapsuleDump.c
> +  AppSupport.c
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +
> +[Guids]
> +  gEfiFileInfoGuid
> +  gEfiPartTypeSystemPartGuid
> +  gEfiGlobalVariableGuid
> +  gEfiCapsuleReportGuid
> +  gEfiFmpCapsuleGuid
> +  gWindowsUxCapsuleGuid
> +  gEfiCertTypeRsa2048Sha256Guid
> +  gEfiCertPkcs7Guid
> +  gEfiSystemResourceTableGuid
> +
> +[Protocols]
> +  gEfiLoadedImageProtocolGuid
> +  gEfiSimpleFileSystemProtocolGuid
> +  gEfiGraphicsOutputProtocolGuid
> +  gEfiFirmwareManagementProtocolGuid
> +
> +[LibraryClasses]
> +  BaseLib
> +  UefiApplicationEntryPoint
> +  DebugLib
> +  MemoryAllocationLib
> +  UefiBootServicesTableLib
> +  UefiRuntimeServicesTableLib
> +  UefiLib
> +  PrintLib
> +  EdkiiSystemCapsuleLib
> +
> +[UserExtensions.TianoCore."ExtraFiles"]
> +  CapsuleAppExtra.uni
> diff --git a/MdeModulePkg/Application/CapsuleApp/CapsuleApp.uni
> b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.uni
> new file mode 100644
> index 0000000..54d6e12
> --- /dev/null
> +++ b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.uni
> @@ -0,0 +1,22 @@
> +// /** @file
> +// A shell application that triggers capsule update process.
> +//
> +// This application can trigger capsule update process. It can also
> +// generate capsule image, or dump capsule variable information.
> +//
> +// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
> +//
> +// This program and the accompanying materials
> +// are licensed and made available under the terms and conditions of the BSD License
> +// which accompanies this distribution. The full text of the license may be found at
> +// http://opensource.org/licenses/bsd-license.php
> +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +//
> +// **/
> +
> +
> +#string STR_MODULE_ABSTRACT             #language en-US "A shell application that
> triggers capsule update process."
> +
> +#string STR_MODULE_DESCRIPTION          #language en-US "This application can trigger
> capsule update process. It can also generate capsule image, or dump capsule variable
> information."
> +
> diff --git a/MdeModulePkg/Application/CapsuleApp/CapsuleAppExtra.uni
> b/MdeModulePkg/Application/CapsuleApp/CapsuleAppExtra.uni
> new file mode 100644
> index 0000000..b5a8840
> --- /dev/null
> +++ b/MdeModulePkg/Application/CapsuleApp/CapsuleAppExtra.uni
> @@ -0,0 +1,19 @@
> +// /** @file
> +// CapsuleApp Localized Strings and Content
> +//
> +// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
> +//
> +// This program and the accompanying materials
> +// are licensed and made available under the terms and conditions of the BSD License
> +// which accompanies this distribution. The full text of the license may be found at
> +// http://opensource.org/licenses/bsd-license.php
> +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +//
> +// **/
> +
> +#string STR_PROPERTIES_MODULE_NAME
> +#language en-US
> +"Capsule Application"
> +
> +
> diff --git a/MdeModulePkg/Application/CapsuleApp/CapsuleDump.c
> b/MdeModulePkg/Application/CapsuleApp/CapsuleDump.c
> new file mode 100644
> index 0000000..c56f41f
> --- /dev/null
> +++ b/MdeModulePkg/Application/CapsuleApp/CapsuleDump.c
> @@ -0,0 +1,840 @@
> +/** @file
> +  Dump Capsule image information.
> +
> +  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the BSD License
> +  which accompanies this distribution.  The full text of the license may be found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +
> +**/
> +
> +#include <PiDxe.h>
> +#include <Library/BaseLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/UefiRuntimeServicesTableLib.h>
> +#include <Library/UefiLib.h>
> +#include <Library/PrintLib.h>
> +#include <Library/EdkiiSystemCapsuleLib.h>
> +#include <Protocol/FirmwareManagement.h>
> +#include <Guid/ImageAuthentication.h>
> +#include <Guid/EdkiiSystemFmpCapsule.h>
> +#include <Guid/CapsuleReport.h>
> +#include <Guid/SystemResourceTable.h>
> +#include <Guid/FmpCapsule.h>
> +#include <IndustryStandard/WindowsUxCapsule.h>
> +
> +/**
> +  Read a file.
> +
> +  @param FileName        The file to be read.
> +  @param BufferSize      The file buffer size
> +  @param Buffer          The file buffer
> +
> +  @retval EFI_SUCCESS    Read file successfully
> +  @retval EFI_NOT_FOUND  File not found
> +**/
> +EFI_STATUS
> +ReadFileToBuffer(
> +  IN  CHAR16                               *FileName,
> +  OUT UINTN                                *BufferSize,
> +  OUT VOID                                 **Buffer
> +  );
> +
> +extern UINTN  Argc;
> +extern CHAR16 *Argv[];
> +
> +/**
> +  Dump UX capsule information.
> +
> +  @param CapsuleHeader      The UX capsule header
> +**/
> +VOID
> +DumpUxCapsule(
> +  IN EFI_CAPSULE_HEADER  *CapsuleHeader
> +  )
> +{
> +  EFI_DISPLAY_CAPSULE                           *DisplayCapsule;
> +  DisplayCapsule = (EFI_DISPLAY_CAPSULE *)CapsuleHeader;
> +  Print(L"[UxCapusule]\n");
> +  Print(L"CapsuleHeader:\n");
> +  Print(L"  CapsuleGuid      - %g\n", &DisplayCapsule->CapsuleHeader.CapsuleGuid);
> +  Print(L"  HeaderSize       - 0x%x\n", DisplayCapsule->CapsuleHeader.HeaderSize);
> +  Print(L"  Flags            - 0x%x\n", DisplayCapsule->CapsuleHeader.Flags);
> +  Print(L"  CapsuleImageSize - 0x%x\n", DisplayCapsule-
> >CapsuleHeader.CapsuleImageSize);
> +  Print(L"ImagePayload:\n");
> +  Print(L"  Version          - 0x%x\n", DisplayCapsule->ImagePayload.Version);
> +  Print(L"  Checksum         - 0x%x\n", DisplayCapsule->ImagePayload.Checksum);
> +  Print(L"  ImageType        - 0x%x\n", DisplayCapsule->ImagePayload.ImageType);
> +  Print(L"  Mode             - 0x%x\n", DisplayCapsule->ImagePayload.Mode);
> +  Print(L"  OffsetX          - 0x%x\n", DisplayCapsule->ImagePayload.OffsetX);
> +  Print(L"  OffsetY          - 0x%x\n", DisplayCapsule->ImagePayload.OffsetY);
> +}
> +
> +/**
> +  Dump FMP image authentication information.
> +
> +  @param Image      The FMP capsule image
> +  @param ImageSize  The size of the FMP capsule image in bytes.
> +
> +  @return the size of FMP authentication.
> +**/
> +UINTN
> +DumpImageAuthentication(
> +  IN VOID   *Image,
> +  IN UINTN  ImageSize
> +  )
> +{
> +  EFI_FIRMWARE_IMAGE_AUTHENTICATION             *ImageAuthentication;
> +
> +  ImageAuthentication = Image;
> +  if (CompareGuid(&ImageAuthentication->AuthInfo.CertType, &gEfiCertPkcs7Guid) ||
> +      CompareGuid(&ImageAuthentication->AuthInfo.CertType,
> &gEfiCertTypeRsa2048Sha256Guid)) {
> +    Print(L"[ImageAuthentication]\n");
> +    Print(L"  MonotonicCount   - 0x%lx\n", ImageAuthentication->MonotonicCount);
> +    Print(L"WIN_CERTIFICATE:\n");
> +    Print(L"  dwLength         - 0x%x\n", ImageAuthentication->AuthInfo.Hdr.dwLength);
> +    Print(L"  wRevision        - 0x%x\n", ImageAuthentication-
> >AuthInfo.Hdr.wRevision);
> +    Print(L"  wCertificateType - 0x%x\n", ImageAuthentication-
> >AuthInfo.Hdr.wCertificateType);
> +    Print(L"  CertType         - %g\n", &ImageAuthentication->AuthInfo.CertType);
> +    return sizeof(ImageAuthentication->MonotonicCount) + ImageAuthentication-
> >AuthInfo.Hdr.dwLength;
> +  } else {
> +    return 0;
> +  }
> +}
> +
> +/**
> +  Dump EDKII system FMP capsule.
> +
> +  @param Image      The EDKII system FMP capsule.
> +  @param ImageSize  The size of the EDKII system FMP capsule in bytes.
> +**/
> +VOID
> +DumpEdkiiSystemFmpCapsule(
> +  IN VOID   *Image,
> +  IN UINTN  ImageSize
> +  )
> +{
> +  UINTN                                         ImageOffset;
> +  VOID                                          *BiosImage;
> +  UINTN                                         BiosImageSize;
> +  BOOLEAN                                       Result;
> +  EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR        *TempImageFmpInfo;
> +  EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR        *ImageFmpInfo;
> +  UINTN                                         ImageFmpInfoSize;
> +
> +  //
> +  // We do not know if there is EFI_FIRMWARE_IMAGE_AUTHENTICATION.
> +  // so just *try* to parse it
> +  //
> +  ImageOffset = DumpImageAuthentication(Image, ImageSize);
> +  Image = (UINT8 *)Image + ImageOffset;
> +  ImageSize -= ImageOffset;
> +  Print(L"[Image]\n");
> +  Print(L"  ImageSize   - 0x%x\n", ImageSize);
> +
> +  Result = ExtractConfigImage(Image, ImageSize, &BiosImage, &BiosImageSize);
> +  if (Result) {
> +    Print(L"  ConfigFileSize  - 0x%x\n", BiosImageSize);
> +  }
> +  Result = ExtractDriverFvImage(Image, ImageSize, &BiosImage, &BiosImageSize);
> +  if (Result) {
> +    Print(L"  DriverFvSize    - 0x%x\n", BiosImageSize);
> +  }
> +  Result = ExtractSystemFirmwareImage(Image, ImageSize, &BiosImage, &BiosImageSize);
> +  if (Result) {
> +    Print(L"  BiosImageSize   - 0x%x\n", BiosImageSize);
> +  }
> +  Result = ExtractSystemFirmwareImageFmpInfo(BiosImage, BiosImageSize,
> &TempImageFmpInfo, &ImageFmpInfoSize);
> +  if (Result) {
> +    ImageFmpInfo = AllocateCopyPool(ImageFmpInfoSize, TempImageFmpInfo);
> +    if (ImageFmpInfo != NULL) {
> +      Print(L"[ImageFmpInfo]\n");
> +      Print(L"  Signature                      - 0x%x\n", ImageFmpInfo->Signature);
> +      Print(L"  HeaderLength                   - 0x%x\n", ImageFmpInfo->HeaderLength);
> +      Print(L"  Length                         - 0x%x\n", ImageFmpInfo->Length);
> +      Print(L"  PackageVersion                 - 0x%x\n", ImageFmpInfo-
> >PackageVersion);
> +      Print(L"  PackageVersionNameStringOffset - 0x%x\n", ImageFmpInfo-
> >PackageVersionNameStringOffset);
> +      if (ImageFmpInfo->PackageVersionNameStringOffset != 0) {
> +        Print(L"                                 - %s\n", (UINT8 *)ImageFmpInfo +
> ImageFmpInfo->PackageVersionNameStringOffset);
> +      }
> +      Print(L"  ImageIndex                     - 0x%x\n", ImageFmpInfo->ImageIndex);
> +      Print(L"  ImageTypeId                    - %g\n", &ImageFmpInfo->ImageTypeId);
> +      Print(L"  ImageId                        - 0x%lx\n", ImageFmpInfo->ImageId);
> +      Print(L"  ImageIdNameStringOffset        - 0x%x\n", ImageFmpInfo-
> >ImageIdNameStringOffset);
> +      if (ImageFmpInfo->ImageIdNameStringOffset != 0) {
> +        Print(L"                                 - %s\n", (UINT8 *)ImageFmpInfo +
> ImageFmpInfo->ImageIdNameStringOffset);
> +      }
> +      Print(L"  Version                        - 0x%x\n", ImageFmpInfo->Version);
> +      Print(L"  VersionNameStringOffset        - 0x%x\n", ImageFmpInfo-
> >VersionNameStringOffset);
> +      if (ImageFmpInfo->VersionNameStringOffset != 0) {
> +        Print(L"                                 - %s\n", (UINT8 *)ImageFmpInfo +
> ImageFmpInfo->VersionNameStringOffset);
> +      }
> +      Print(L"  Size                           - 0x%lx\n", ImageFmpInfo->Size);
> +      Print(L"  AttributesSupported            - 0x%lx\n", ImageFmpInfo-
> >AttributesSupported);
> +      Print(L"  AttributesSetting              - 0x%lx\n", ImageFmpInfo-
> >AttributesSetting);
> +      Print(L"  Compatibilities                - 0x%lx\n", ImageFmpInfo-
> >Compatibilities);
> +      Print(L"  LowestSupportedImageVersion    - 0x%x\n", ImageFmpInfo-
> >LowestSupportedImageVersion);
> +      Print(L"  LastAttemptVersion             - 0x%x\n", ImageFmpInfo-
> >LastAttemptVersion);
> +      Print(L"  LastAttemptStatus              - 0x%x\n", ImageFmpInfo-
> >LastAttemptStatus);
> +      Print(L"  HardwareInstance               - 0x%lx\n", ImageFmpInfo-
> >HardwareInstance);
> +      Print(L"  Version                        - 0x%x\n", ImageFmpInfo->Version);
> +      FreePool(ImageFmpInfo);
> +    }
> +  }
> +}
> +
> +/**
> +  Dump a non-nested FMP capsule.
> +
> +  @param  CapsuleHeader  A pointer to CapsuleHeader
> +  @param  IsSystemFmp    If it is a system FMP
> +**/
> +VOID
> +DumpFmpCapsule(
> +  IN EFI_CAPSULE_HEADER  *CapsuleHeader,
> +  IN BOOLEAN             IsSystemFmp
> +  )
> +{
> +  EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER        *FmpCapsuleHeader;
> +  UINT64                                        *ItemOffsetList;
> +  UINTN                                         Index;
> +  UINTN                                         Count;
> +  EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER  *FmpImageHeader;
> +  VOID                                          *Image;
> +
> +  Print(L"[FmpCapusule]\n");
> +  Print(L"CapsuleHeader:\n");
> +  Print(L"  CapsuleGuid      - %g\n", &CapsuleHeader->CapsuleGuid);
> +  Print(L"  HeaderSize       - 0x%x\n", CapsuleHeader->HeaderSize);
> +  Print(L"  Flags            - 0x%x\n", CapsuleHeader->Flags);
> +  Print(L"  CapsuleImageSize - 0x%x\n", CapsuleHeader->CapsuleImageSize);
> +
> +  FmpCapsuleHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *)((UINT8 *)CapsuleHeader
> + CapsuleHeader->HeaderSize);
> +  ItemOffsetList = (UINT64 *)(FmpCapsuleHeader + 1);
> +  Print(L"FmpHeader:\n");
> +  Print(L"  Version             - 0x%x\n", FmpCapsuleHeader->Version);
> +  Print(L"  EmbeddedDriverCount - 0x%x\n", FmpCapsuleHeader->EmbeddedDriverCount);
> +  Print(L"  PayloadItemCount    - 0x%x\n", FmpCapsuleHeader->PayloadItemCount);
> +  Count = FmpCapsuleHeader->EmbeddedDriverCount + FmpCapsuleHeader->PayloadItemCount;
> +  for (Index = 0; Index < Count; Index++) {
> +    Print(L"  Offset[%d]           - 0x%x\n", Index, ItemOffsetList[Index]);
> +  }
> +
> +  for (Index = FmpCapsuleHeader->EmbeddedDriverCount; Index < Count; Index++) {
> +    Print(L"FmpPayload[%d] ImageHeader:\n", Index);
> +    FmpImageHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *)((UINT8
> *)FmpCapsuleHeader + ItemOffsetList[Index]);
> +    Print(L"  Version                - 0x%x\n", FmpImageHeader->Version);
> +    Print(L"  UpdateImageTypeId      - %g\n", &FmpImageHeader->UpdateImageTypeId);
> +    Print(L"  UpdateImageIndex       - 0x%x\n", FmpImageHeader->UpdateImageIndex);
> +    Print(L"  UpdateImageSize        - 0x%x\n", FmpImageHeader->UpdateImageSize);
> +    Print(L"  UpdateVendorCodeSize   - 0x%x\n", FmpImageHeader->UpdateVendorCodeSize);
> +    if (FmpImageHeader->Version >=
> EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {
> +      Print(L"  UpdateHardwareInstance - 0x%lx\n", FmpImageHeader-
> >UpdateHardwareInstance);
> +    }
> +    if (FmpImageHeader->Version >=
> EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {
> +      Image = (UINT8 *)(FmpImageHeader + 1);
> +    }  else {
> +      Image = (UINT8 *)FmpImageHeader +
> OFFSET_OF(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER, UpdateHardwareInstance);
> +    }
> +    if (IsSystemFmp) {
> +      DumpEdkiiSystemFmpCapsule(Image, FmpImageHeader->UpdateImageSize);
> +    }
> +  }
> +}
> +
> +/**
> +  Return if there is a FMP header below capsule header.
> +
> +  @param[in] CapsuleHeader A pointer to EFI_CAPSULE_HEADER
> +
> +  @retval TRUE  There is a FMP header below capsule header.
> +  @retval FALSE There is not a FMP header below capsule header
> +**/
> +BOOLEAN
> +IsNestedFmpCapsule(
> +  IN EFI_CAPSULE_HEADER         *CapsuleHeader
> +  )
> +{
> +  EFI_STATUS                 Status;
> +  EFI_SYSTEM_RESOURCE_TABLE  *Esrt;
> +  EFI_SYSTEM_RESOURCE_ENTRY  *EsrtEntry;
> +  UINTN                      Index;
> +  BOOLEAN                    EsrtGuidFound;
> +  EFI_CAPSULE_HEADER         *NestedCapsuleHeader;
> +  UINTN                      NestedCapsuleSize;
> +
> +  //
> +  // Check ESRT
> +  //
> +  EsrtGuidFound = FALSE;
> +  Status = EfiGetSystemConfigurationTable(&gEfiSystemResourceTableGuid, (VOID
> **)&Esrt);
> +  if (!EFI_ERROR(Status)) {
> +    EsrtEntry = (VOID *)(Esrt + 1);
> +    for (Index = 0; Index < Esrt->FwResourceCount; Index++, EsrtEntry++) {
> +      if (CompareGuid(&EsrtEntry->FwClass, &CapsuleHeader->CapsuleGuid)) {
> +        EsrtGuidFound = TRUE;
> +        break;
> +      }
> +    }
> +  }
> +
> +  if (!EsrtGuidFound) {
> +    return FALSE;
> +  }
> +
> +  //
> +  // Check nested capsule header
> +  // FMP GUID after ESRT one
> +  //
> +  NestedCapsuleHeader = (EFI_CAPSULE_HEADER *)((UINT8 *)CapsuleHeader + CapsuleHeader-
> >HeaderSize);
> +  NestedCapsuleSize = (UINTN)CapsuleHeader + CapsuleHeader->HeaderSize -
> (UINTN)NestedCapsuleHeader;
> +  if (NestedCapsuleSize < sizeof(EFI_CAPSULE_HEADER)) {
> +    return FALSE;
> +  }
> +  if (!CompareGuid(&NestedCapsuleHeader->CapsuleGuid, &gEfiFmpCapsuleGuid)) {
> +    return FALSE;
> +  }
> +  return TRUE;
> +}
> +
> +/**
> +  Dump capsule information
> +
> +  @retval EFI_SUCCESS            The capsule information is dumped.
> +  @retval EFI_UNSUPPORTED        Input parameter is not valid.
> +**/
> +EFI_STATUS
> +DumpCapsule(
> +  VOID
> +  )
> +{
> +  CHAR16                                        *CapsuleName;
> +  VOID                                          *Buffer;
> +  UINTN                                         FileSize;
> +  BOOLEAN                                       IsSystemFmp;
> +  EFI_CAPSULE_HEADER                            *CapsuleHeader;
> +  EFI_STATUS                                    Status;
> +
> +  if (Argc != 3) {
> +    Print(L"CapsuleApp: Invalid Parameter.\n");
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  IsSystemFmp = FALSE;
> +  if (StrCmp(Argv[1], L"-DS") == 0) {
> +    IsSystemFmp = TRUE;
> +  }
> +
> +  CapsuleName = Argv[2];
> +  Status = ReadFileToBuffer(CapsuleName, &FileSize, &Buffer);
> +  if (EFI_ERROR(Status)) {
> +    Print(L"CapsuleApp: Capsule (%s) is not found.\n", CapsuleName);
> +    goto Done;
> +  }
> +
> +  CapsuleHeader = Buffer;
> +  if (CompareGuid(&CapsuleHeader->CapsuleGuid, &gWindowsUxCapsuleGuid)) {
> +    DumpUxCapsule(CapsuleHeader);
> +    Status = EFI_SUCCESS;
> +    goto Done;
> +  }
> +
> +  if (CompareGuid(&CapsuleHeader->CapsuleGuid, &gEfiFmpCapsuleGuid)) {
> +    DumpFmpCapsule(CapsuleHeader, IsSystemFmp);
> +  }
> +  if (IsNestedFmpCapsule(CapsuleHeader)) {
> +    Print(L"[NestedCapusule]\n");
> +    Print(L"CapsuleHeader:\n");
> +    Print(L"  CapsuleGuid      - %g\n", &CapsuleHeader->CapsuleGuid);
> +    Print(L"  HeaderSize       - 0x%x\n", CapsuleHeader->HeaderSize);
> +    Print(L"  Flags            - 0x%x\n", CapsuleHeader->Flags);
> +    Print(L"  CapsuleImageSize - 0x%x\n", CapsuleHeader->CapsuleImageSize);
> +    DumpFmpCapsule((EFI_CAPSULE_HEADER *)((UINTN)CapsuleHeader + CapsuleHeader-
> >HeaderSize), IsSystemFmp);
> +  }
> +
> +Done:
> +  FreePool(Buffer);
> +  return Status;
> +}
> +
> +/**
> +  Dump capsule status variable.
> +
> +  @retval EFI_SUCCESS            The capsule status variable is dumped.
> +  @retval EFI_UNSUPPORTED        Input parameter is not valid.
> +**/
> +EFI_STATUS
> +DmpCapsuleStatusVariable(
> +  VOID
> +  )
> +{
> +  EFI_STATUS                          Status;
> +  UINT32                              Index;
> +  CHAR16                              CapsuleVarName[20];
> +  CHAR16                              *TempVarName;
> +  EFI_CAPSULE_RESULT_VARIABLE_HEADER  *CapsuleResult;
> +  EFI_CAPSULE_RESULT_VARIABLE_FMP     *CapsuleResultFmp;
> +  UINTN                               CapsuleFileNameSize;
> +  CHAR16                              CapsuleIndexData[12];
> +  CHAR16                              *CapsuleIndex;
> +
> +  Status = GetVariable2(
> +             L"CapsuleMax",
> +             &gEfiCapsuleReportGuid,
> +             (VOID **)&CapsuleIndex,
> +             NULL
> +             );
> +  if (!EFI_ERROR(Status)) {
> +    CopyMem(CapsuleIndexData, CapsuleIndex, 11 * sizeof(CHAR16));
> +    CapsuleIndexData[11] = 0;
> +    Print(L"CapsuleMax - %s\n", CapsuleIndexData);
> +    FreePool(CapsuleIndex);
> +  }
> +  Status = GetVariable2(
> +             L"CapsuleLast",
> +             &gEfiCapsuleReportGuid,
> +             (VOID **)&CapsuleIndex,
> +             NULL
> +             );
> +  if (!EFI_ERROR(Status)) {
> +    CopyMem(CapsuleIndexData, CapsuleIndex, 11 * sizeof(CHAR16));
> +    CapsuleIndexData[11] = 0;
> +    Print(L"CapsuleLast - %s\n", CapsuleIndexData);
> +    FreePool(CapsuleIndex);
> +  }
> +
> +
> +  StrCpyS (CapsuleVarName, sizeof(CapsuleVarName)/sizeof(CapsuleVarName[0]),
> L"Capsule");
> +  TempVarName = CapsuleVarName + StrLen (CapsuleVarName);
> +  Index = 0;
> +
> +  while (TRUE) {
> +    UnicodeSPrint (TempVarName, 5 * sizeof(CHAR16), L"%04x", Index);
> +
> +    Status = GetVariable2 (
> +               CapsuleVarName,
> +               &gEfiCapsuleReportGuid,
> +               (VOID **) &CapsuleResult,
> +               NULL
> +               );
> +    if (Status == EFI_NOT_FOUND) {
> +      break;
> +    } else if (EFI_ERROR(Status)) {
> +      continue;
> +    }
> +
> +    //
> +    // display capsule process status
> +    //
> +    if (CapsuleResult->VariableTotalSize >=
> sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER)) {
> +      Print (L"CapsuleName: %s\n", CapsuleVarName);
> +      Print (L"  Capsule Guid: %g\n", &CapsuleResult->CapsuleGuid);
> +      Print (L"  Capsule ProcessedTime: %t\n", &CapsuleResult->CapsuleProcessed);
> +      Print (L"  Capsule Status: %r\n", CapsuleResult->CapsuleStatus);
> +    }
> +
> +    if (CompareGuid(&CapsuleResult->CapsuleGuid, &gEfiFmpCapsuleGuid)) {
> +      if (CapsuleResult->VariableTotalSize >=
> sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER) + sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP)) {
> +        CapsuleResultFmp = (EFI_CAPSULE_RESULT_VARIABLE_FMP *)(CapsuleResult + 1);
> +        Print(L"  Capsule FMP Version: 0x%x\n", CapsuleResultFmp->Version);
> +        Print(L"  Capsule FMP PayloadIndex: 0x%x\n", CapsuleResultFmp->PayloadIndex);
> +        Print(L"  Capsule FMP UpdateImageIndex: 0x%x\n", CapsuleResultFmp-
> >UpdateImageIndex);
> +        Print(L"  Capsule FMP UpdateImageTypeId: %g\n", &CapsuleResultFmp-
> >UpdateImageTypeId);
> +        if (CapsuleResult->VariableTotalSize >
> sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER) + sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP)) {
> +          Print(L"  Capsule FMP CapsuleFileName: %s\n", (CapsuleResultFmp + 1));
> +          CapsuleFileNameSize = StrSize((CHAR16 *)(CapsuleResultFmp + 1));
> +          if (CapsuleResult->VariableTotalSize >
> sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER) + sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP) +
> CapsuleFileNameSize) {
> +            Print(L"  Capsule FMP CapsuleTarget: %s\n", (UINT8 *)(CapsuleResultFmp +
> 1) + CapsuleFileNameSize);
> +          }
> +        }
> +      }
> +    }
> +
> +    FreePool(CapsuleResult);
> +
> +    Index++;
> +    if (Index > 0xFFFF) {
> +      break;
> +    }
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +CHAR8 *mFwTypeString[] = {
> +  "Unknown",
> +  "SystemFirmware",
> +  "DeviceFirmware",
> +  "UefiDriver",
> +};
> +
> +CHAR8 *mLastAttemptStatusString[] = {
> +  "Success",
> +  "Error: Unsuccessful",
> +  "Error: Insufficient Resources",
> +  "Error: Incorrect Version",
> +  "Error: Invalid Format",
> +  "Error: Auth Error",
> +  "Error: Power Event AC",
> +  "Error: Power Event Battery",
> +};
> +
> +/**
> +  Convert FwType to a string.
> +
> +  @param FwType  FwType in ESRT
> +
> +  @return a string for FwType.
> +**/
> +CHAR8 *
> +FwTypeToString(
> +  IN UINT32 FwType
> +  )
> +{
> +  if (FwType < sizeof(mFwTypeString) / sizeof(mFwTypeString[0])) {
> +    return mFwTypeString[FwType];
> +  } else {
> +    return "Invalid";
> +  }
> +}
> +
> +/**
> +  Convert LastAttemptStatus to a string.
> +
> +  @param LastAttemptStatus  LastAttemptStatus in FMP or ESRT
> +
> +  @return a string for LastAttemptStatus.
> +**/
> +CHAR8 *
> +LastAttemptStatusToString(
> +  IN UINT32 LastAttemptStatus
> +  )
> +{
> +  if (LastAttemptStatus < sizeof(mLastAttemptStatusString) /
> sizeof(mLastAttemptStatusString[0])) {
> +    return mLastAttemptStatusString[LastAttemptStatus];
> +  } else {
> +    return "Error: Unknown";
> +  }
> +}
> +
> +/**
> +  Dump ESRT entry.
> +
> +  @param EsrtEntry  ESRT entry
> +**/
> +VOID
> +DumpEsrtEntry(
> +  IN EFI_SYSTEM_RESOURCE_ENTRY  *EsrtEntry
> +  )
> +{
> +  Print(L"  FwClass                  - %g\n", &EsrtEntry->FwClass);
> +  Print(L"  FwType                   - 0x%x (%a)\n", EsrtEntry->FwType,
> FwTypeToString(EsrtEntry->FwType));
> +  Print(L"  FwVersion                - 0x%x\n", EsrtEntry->FwVersion);
> +  Print(L"  LowestSupportedFwVersion - 0x%x\n", EsrtEntry->LowestSupportedFwVersion);
> +  Print(L"  CapsuleFlags             - 0x%x\n", EsrtEntry->CapsuleFlags);
> +  Print(L"    PERSIST_ACROSS_RESET   - 0x%x\n", EsrtEntry->CapsuleFlags &
> CAPSULE_FLAGS_PERSIST_ACROSS_RESET);
> +  Print(L"    POPULATE_SYSTEM_TABLE  - 0x%x\n", EsrtEntry->CapsuleFlags &
> CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE);
> +  Print(L"    INITIATE_RESET         - 0x%x\n", EsrtEntry->CapsuleFlags &
> CAPSULE_FLAGS_INITIATE_RESET);
> +  Print(L"  LastAttemptVersion       - 0x%x\n", EsrtEntry->LastAttemptVersion);
> +  Print(L"  LastAttemptStatus        - 0x%x (%a)\n", EsrtEntry->LastAttemptStatus,
> LastAttemptStatusToString(EsrtEntry->LastAttemptStatus));
> +}
> +
> +/**
> +  Dump ESRT table.
> +
> +  @param Esrt  ESRT table
> +**/
> +VOID
> +DumpEsrt(
> +  IN EFI_SYSTEM_RESOURCE_TABLE  *Esrt
> +  )
> +{
> +  UINTN                      Index;
> +  EFI_SYSTEM_RESOURCE_ENTRY  *EsrtEntry;
> +
> +  Print(L"EFI_SYSTEM_RESOURCE_TABLE:\n");
> +  Print(L"FwResourceCount    - 0x%x\n", Esrt->FwResourceCount);
> +  Print(L"FwResourceCountMax - 0x%x\n", Esrt->FwResourceCountMax);
> +  Print(L"FwResourceVersion  - 0x%lx\n", Esrt->FwResourceVersion);
> +
> +  EsrtEntry = (VOID *)(Esrt + 1);
> +  for (Index = 0; Index < Esrt->FwResourceCount; Index++) {
> +    Print(L"EFI_SYSTEM_RESOURCE_ENTRY (%d):\n", Index);
> +    DumpEsrtEntry(EsrtEntry);
> +    EsrtEntry++;
> +  }
> +}
> +
> +/**
> +  Dump ESRT info.
> +**/
> +VOID
> +DumpEsrtData (
> +  VOID
> +  )
> +{
> +  EFI_STATUS                 Status;
> +  EFI_SYSTEM_RESOURCE_TABLE  *Esrt;
> +
> +  Print(L"##############\n");
> +  Print(L"# ESRT TABLE #\n");
> +  Print(L"##############\n");
> +
> +  Status = EfiGetSystemConfigurationTable (&gEfiSystemResourceTableGuid, (VOID
> **)&Esrt);
> +  if (EFI_ERROR(Status)) {
> +    Print(L"ESRT - %r\n", Status);
> +    return;
> +  }
> +  DumpEsrt(Esrt);
> +  Print(L"\n");
> +}
> +
> +/**
> +  Dump FMP information.
> +
> +  @param ImageInfoSize       The size of ImageInfo, in bytes.
> +  @param ImageInfo           A pointer to EFI_FIRMWARE_IMAGE_DESCRIPTOR.
> +  @param DescriptorVersion   The version of EFI_FIRMWARE_IMAGE_DESCRIPTOR.
> +  @param DescriptorCount     The count of EFI_FIRMWARE_IMAGE_DESCRIPTOR.
> +  @param DescriptorSize      The size of an individual EFI_FIRMWARE_IMAGE_DESCRIPTOR,
> in bytes.
> +  @param PackageVersion      The version of package.
> +  @param PackageVersionName  The version name of package.
> +**/
> +VOID
> +DumpFmpImageInfo(
> +  IN UINTN                           ImageInfoSize,
> +  IN EFI_FIRMWARE_IMAGE_DESCRIPTOR   *ImageInfo,
> +  IN UINT32                          DescriptorVersion,
> +  IN UINT8                           DescriptorCount,
> +  IN UINTN                           DescriptorSize,
> +  IN UINT32                          PackageVersion,
> +  IN CHAR16                          *PackageVersionName
> +  )
> +{
> +  EFI_FIRMWARE_IMAGE_DESCRIPTOR                 *CurrentImageInfo;
> +  UINTN                                         Index;
> +
> +  Print(L"  DescriptorVersion  - 0x%x\n", DescriptorVersion);
> +  Print(L"  DescriptorCount    - 0x%x\n", DescriptorCount);
> +  Print(L"  DescriptorSize     - 0x%x\n", DescriptorSize);
> +  Print(L"  PackageVersion     - 0x%x\n", PackageVersion);
> +  Print(L"  PackageVersionName - \"%s\"\n", PackageVersionName);
> +  CurrentImageInfo = ImageInfo;
> +  for (Index = 0; Index < DescriptorCount; Index++) {
> +    Print(L"  ImageDescriptor (%d)\n", Index);
> +    Print(L"    ImageIndex                  - 0x%x\n", CurrentImageInfo->ImageIndex);
> +    Print(L"    ImageTypeId                 - %g\n", &CurrentImageInfo->ImageTypeId);
> +    Print(L"    ImageId                     - 0x%lx\n", CurrentImageInfo->ImageId);
> +    Print(L"    ImageIdName                 - \"%s\"\n", CurrentImageInfo-
> >ImageIdName);
> +    Print(L"    Version                     - 0x%x\n", CurrentImageInfo->Version);
> +    Print(L"    VersionName                 - \"%s\"\n", CurrentImageInfo-
> >VersionName);
> +    Print(L"    Size                        - 0x%x\n", CurrentImageInfo->Size);
> +    Print(L"    AttributesSupported         - 0x%lx\n", CurrentImageInfo-
> >AttributesSupported);
> +    Print(L"      IMAGE_UPDATABLE           - 0x%lx\n", CurrentImageInfo-
> >AttributesSupported & IMAGE_ATTRIBUTE_IMAGE_UPDATABLE);
> +    Print(L"      RESET_REQUIRED            - 0x%lx\n", CurrentImageInfo-
> >AttributesSupported & IMAGE_ATTRIBUTE_RESET_REQUIRED);
> +    Print(L"      AUTHENTICATION_REQUIRED   - 0x%lx\n", CurrentImageInfo-
> >AttributesSupported & IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);
> +    Print(L"      IN_USE                    - 0x%lx\n", CurrentImageInfo-
> >AttributesSupported & IMAGE_ATTRIBUTE_IN_USE);
> +    Print(L"      UEFI_IMAGE                - 0x%lx\n", CurrentImageInfo-
> >AttributesSupported & IMAGE_ATTRIBUTE_UEFI_IMAGE);
> +    Print(L"    AttributesSetting           - 0x%lx\n", CurrentImageInfo-
> >AttributesSetting);
> +    Print(L"      IMAGE_UPDATABLE           - 0x%lx\n", CurrentImageInfo-
> >AttributesSetting & IMAGE_ATTRIBUTE_IMAGE_UPDATABLE);
> +    Print(L"      RESET_REQUIRED            - 0x%lx\n", CurrentImageInfo-
> >AttributesSetting & IMAGE_ATTRIBUTE_RESET_REQUIRED);
> +    Print(L"      AUTHENTICATION_REQUIRED   - 0x%lx\n", CurrentImageInfo-
> >AttributesSetting & IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);
> +    Print(L"      IN_USE                    - 0x%lx\n", CurrentImageInfo-
> >AttributesSetting & IMAGE_ATTRIBUTE_IN_USE);
> +    Print(L"      UEFI_IMAGE                - 0x%lx\n", CurrentImageInfo-
> >AttributesSetting & IMAGE_ATTRIBUTE_UEFI_IMAGE);
> +    Print(L"    Compatibilities             - 0x%lx\n", CurrentImageInfo-
> >Compatibilities);
> +    Print(L"      COMPATIB_CHECK_SUPPORTED  - 0x%lx\n", CurrentImageInfo-
> >Compatibilities & IMAGE_COMPATIBILITY_CHECK_SUPPORTED);
> +    if (DescriptorVersion > 1) {
> +      Print(L"    LowestSupportedImageVersion - 0x%x\n", CurrentImageInfo-
> >LowestSupportedImageVersion);
> +      if (DescriptorVersion > 2) {
> +        Print(L"    LastAttemptVersion          - 0x%x\n", CurrentImageInfo-
> >LastAttemptVersion);
> +        Print(L"    LastAttemptStatus           - 0x%x (%a)\n", CurrentImageInfo-
> >LastAttemptStatus, LastAttemptStatusToString(CurrentImageInfo->LastAttemptStatus));
> +        Print(L"    HardwareInstance            - 0x%lx\n", CurrentImageInfo-
> >HardwareInstance);
> +      }
> +    }
> +    //
> +    // Use DescriptorSize to move ImageInfo Pointer to stay compatible with different
> ImageInfo version
> +    //
> +    CurrentImageInfo = (EFI_FIRMWARE_IMAGE_DESCRIPTOR *)((UINT8 *)CurrentImageInfo +
> DescriptorSize);
> +  }
> +}
> +
> +/**
> +  Dump FMP package information.
> +
> +  @param PackageVersion             The version of package.
> +  @param PackageVersionName         The version name of package.
> +  @param PackageVersionNameMaxLen   The maximum length of PackageVersionName.
> +  @param AttributesSupported        Package attributes that are supported by this
> device.
> +  @param AttributesSetting          Package attributes.
> +**/
> +VOID
> +DumpFmpPackageInfo(
> +  IN UINT32                           PackageVersion,
> +  IN CHAR16                           *PackageVersionName,
> +  IN UINT32                           PackageVersionNameMaxLen,
> +  IN UINT64                           AttributesSupported,
> +  IN UINT64                           AttributesSetting
> +  )
> +{
> +  Print(L"  PackageVersion              - 0x%x\n", PackageVersion);
> +  Print(L"  PackageVersionName          - \"%s\"\n", PackageVersionName);
> +  Print(L"  PackageVersionNameMaxLen    - 0x%x\n", PackageVersionNameMaxLen);
> +  Print(L"  AttributesSupported         - 0x%lx\n", AttributesSupported);
> +  Print(L"    IMAGE_UPDATABLE           - 0x%lx\n", AttributesSupported &
> IMAGE_ATTRIBUTE_IMAGE_UPDATABLE);
> +  Print(L"    RESET_REQUIRED            - 0x%lx\n", AttributesSupported &
> IMAGE_ATTRIBUTE_RESET_REQUIRED);
> +  Print(L"    AUTHENTICATION_REQUIRED   - 0x%lx\n", AttributesSupported &
> IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);
> +  Print(L"  AttributesSetting           - 0x%lx\n", AttributesSetting);
> +  Print(L"    IMAGE_UPDATABLE           - 0x%lx\n", AttributesSetting &
> IMAGE_ATTRIBUTE_IMAGE_UPDATABLE);
> +  Print(L"    RESET_REQUIRED            - 0x%lx\n", AttributesSetting &
> IMAGE_ATTRIBUTE_RESET_REQUIRED);
> +  Print(L"    AUTHENTICATION_REQUIRED   - 0x%lx\n", AttributesSetting &
> IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);
> +}
> +
> +/**
> +  Dump FMP protocol info.
> +**/
> +VOID
> +DumpFmpData (
> +  VOID
> +  )
> +{
> +  EFI_STATUS                                    Status;
> +  EFI_FIRMWARE_MANAGEMENT_PROTOCOL              *Fmp;
> +  EFI_HANDLE                                    *HandleBuffer;
> +  UINTN                                         NumberOfHandles;
> +  UINTN                                         Index;
> +  EFI_FIRMWARE_IMAGE_DESCRIPTOR                 *FmpImageInfoBuf;
> +  UINTN                                         ImageInfoSize;
> +  UINT32                                        FmpImageInfoDescriptorVer;
> +  UINT8                                         FmpImageInfoCount;
> +  UINTN                                         DescriptorSize;
> +  UINT32                                        PackageVersion;
> +  CHAR16                                        *PackageVersionName;
> +  UINT32                                        PackageVersionNameMaxLen;
> +  UINT64                                        AttributesSupported;
> +  UINT64                                        AttributesSetting;
> +
> +  Print(L"############\n");
> +  Print(L"# FMP DATA #\n");
> +  Print(L"############\n");
> +  Status = gBS->LocateHandleBuffer (
> +                  ByProtocol,
> +                  &gEfiFirmwareManagementProtocolGuid,
> +                  NULL,
> +                  &NumberOfHandles,
> +                  &HandleBuffer
> +                  );
> +  if (EFI_ERROR(Status)) {
> +    Print(L"FMP protocol - %r\n", EFI_NOT_FOUND);
> +    return;
> +  }
> +
> +  for (Index = 0; Index < NumberOfHandles; Index++) {
> +    Status = gBS->HandleProtocol(
> +                    HandleBuffer[Index],
> +                    &gEfiFirmwareManagementProtocolGuid,
> +                    (VOID **)&Fmp
> +                    );
> +    if (EFI_ERROR(Status)) {
> +      continue;
> +    }
> +
> +    ImageInfoSize = 0;
> +    Status = Fmp->GetImageInfo (
> +                    Fmp,
> +                    &ImageInfoSize,
> +                    NULL,
> +                    NULL,
> +                    NULL,
> +                    NULL,
> +                    NULL,
> +                    NULL
> +                    );
> +    if (Status != EFI_BUFFER_TOO_SMALL) {
> +      continue;
> +    }
> +
> +    FmpImageInfoBuf = NULL;
> +    FmpImageInfoBuf = AllocateZeroPool (ImageInfoSize);
> +    if (FmpImageInfoBuf == NULL) {
> +      Status = EFI_OUT_OF_RESOURCES;
> +      goto EXIT;
> +    }
> +
> +    PackageVersionName = NULL;
> +    Status = Fmp->GetImageInfo (
> +                    Fmp,
> +                    &ImageInfoSize,               // ImageInfoSize
> +                    FmpImageInfoBuf,              // ImageInfo
> +                    &FmpImageInfoDescriptorVer,   // DescriptorVersion
> +                    &FmpImageInfoCount,           // DescriptorCount
> +                    &DescriptorSize,              // DescriptorSize
> +                    &PackageVersion,              // PackageVersion
> +                    &PackageVersionName           // PackageVersionName
> +                    );
> +
> +    //
> +    // If FMP GetInformation interface failed, skip this resource
> +    //
> +    if (EFI_ERROR(Status)) {
> +      Print(L"FMP (%d) ImageInfo - %r\n", Index, Status);
> +      FreePool(FmpImageInfoBuf);
> +      continue;
> +    }
> +
> +    Print(L"FMP (%d) ImageInfo:\n", Index);
> +    DumpFmpImageInfo(
> +      ImageInfoSize,               // ImageInfoSize
> +      FmpImageInfoBuf,             // ImageInfo
> +      FmpImageInfoDescriptorVer,   // DescriptorVersion
> +      FmpImageInfoCount,           // DescriptorCount
> +      DescriptorSize,              // DescriptorSize
> +      PackageVersion,              // PackageVersion
> +      PackageVersionName           // PackageVersionName
> +      );
> +
> +    if (PackageVersionName != NULL) {
> +      FreePool(PackageVersionName);
> +    }
> +    FreePool(FmpImageInfoBuf);
> +
> +    //
> +    // Get package info
> +    //
> +    PackageVersionName = NULL;
> +    Status = Fmp->GetPackageInfo (
> +                    Fmp,
> +                    &PackageVersion,              // PackageVersion
> +                    &PackageVersionName,          // PackageVersionName
> +                    &PackageVersionNameMaxLen,    // PackageVersionNameMaxLen
> +                    &AttributesSupported,         // AttributesSupported
> +                    &AttributesSetting            // AttributesSetting
> +                    );
> +    if (EFI_ERROR(Status)) {
> +      Print(L"FMP (%d) PackageInfo - %r\n", Index, Status);
> +    } else {
> +      Print(L"FMP (%d) ImageInfo:\n", Index);
> +      DumpFmpPackageInfo(
> +        PackageVersion,              // PackageVersion
> +        PackageVersionName,          // PackageVersionName
> +        PackageVersionNameMaxLen,    // PackageVersionNameMaxLen
> +        AttributesSupported,         // AttributesSupported
> +        AttributesSetting            // AttributesSetting
> +        );
> +
> +      if (PackageVersionName != NULL) {
> +        FreePool(PackageVersionName);
> +      }
> +    }
> +  }
> +  Print(L"\n");
> +
> +EXIT:
> +  FreePool(HandleBuffer);
> +}
> --
> 2.7.4.windows.1
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>
https://lists.01.org/mailman/listinfo/edk2-devel


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

* Re: [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application.
  2016-09-29 19:10         ` Carsey, Jaben
@ 2016-09-30  4:13           ` Ni, Ruiyu
  2016-09-30 15:30             ` Carsey, Jaben
  0 siblings, 1 reply; 83+ messages in thread
From: Ni, Ruiyu @ 2016-09-30  4:13 UTC (permalink / raw)
  To: Carsey, Jaben, Yao, Jiewen, Kinney, Michael D,
	edk2-devel@lists.01.org
  Cc: Tian, Feng, Zhang, Chao B, Gao, Liming, Zeng, Star

Supposing user inputs "CapsuleApp.efi Parameter1 Parameter2".
There is no spec to define what the LoadOption should equal to.
If there is another UEFI Shell implementation, it could interpret the command line then sets only "Parameter1 Parameter2" into LoadOption, or sets "CapsuleApp.efi\tParameter1\tParameter2" to LoadOption, or sets "[Shell]\tCapsuleApp.efi\tParameter1\tParameter2" to LoadOption.
Because it"produces" such LoadOption, it knows how to "consume"/parse it to get the ARGVs.

So I suggest we put the CapsuleApp in ShellPkg and let it use the ShellParameter protocol.

Regards,
Ray

From: Carsey, Jaben
Sent: Friday, September 30, 2016 3:11 AM
To: Ni, Ruiyu <ruiyu.ni@intel.com>; Yao, Jiewen <jiewen.yao@intel.com>; Kinney, Michael D <michael.d.kinney@intel.com>; edk2-devel@lists.01.org
Cc: Tian, Feng <feng.tian@intel.com>; Zhang, Chao B <chao.b.zhang@intel.com>; Gao, Liming <liming.gao@intel.com>; Zeng, Star <star.zeng@intel.com>; Carsey, Jaben <jaben.carsey@intel.com>
Subject: RE: [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application.

I am confused.

Why is LoadOption and LoadOptionSize not working?  This is specified as part of UEFI Spec (Note: Not UEFI Shell Spec) as a standard way to pass parameters to UEFI appliations.  I think this should work (although it is more work than just examining argc/argv).

-Jaben

From: Ni, Ruiyu
Sent: Wednesday, September 28, 2016 11:40 PM
To: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>; edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>
Cc: Tian, Feng <feng.tian@intel.com<mailto:feng.tian@intel.com>>; Zhang, Chao B <chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com>>; Gao, Liming <liming.gao@intel.com<mailto:liming.gao@intel.com>>; Zeng, Star <star.zeng@intel.com<mailto:star.zeng@intel.com>>; Carsey, Jaben <jaben.carsey@intel.com<mailto:jaben.carsey@intel.com>>
Subject: RE: [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application.
Importance: High

Jiewen,
The way CapsuleApp extracts the ARGV assumes UEFI Shell encodes the parameters using a certain way. But the parameter encoding way is not described in the Shell spec.
Maybe we can put the CapsuleApp in ShellPkg, then let it directly use ShellParameter protocol to get the ARGV.

Copying Jaben.

Regards,
Ray

From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of Yao, Jiewen
Sent: Thursday, September 29, 2016 10:37 AM
To: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>; edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>
Cc: Tian, Feng <feng.tian@intel.com<mailto:feng.tian@intel.com>>; Zhang, Chao B <chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com>>; Gao, Liming <liming.gao@intel.com<mailto:liming.gao@intel.com>>; Zeng, Star <star.zeng@intel.com<mailto:star.zeng@intel.com>>
Subject: Re: [edk2] [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application.

Right. CapsuleOnDisk is not supported in BIOS yet.
I will remove it in CapsuleApp.

CapsuleApp just works as an agent to pass capsule to CapsuleDxeRuntime driver.
So it is checked by CapsuleDxeRuntime, not CapsuleApp.

Thank you
Yao Jiewen

From: Kinney, Michael D
Sent: Thursday, September 29, 2016 9:06 AM
To: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>; Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>
Cc: Tian, Feng <feng.tian@intel.com<mailto:feng.tian@intel.com>>; Zeng, Star <star.zeng@intel.com<mailto:star.zeng@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: [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application.

Jiewen,

Does the capsule on disk feature provided by this app work?

I tried it with the QuarkPlatformPkg capsule and I can get
The app to copy the capsule to an EFI System Partition, but
The logic after that point looks incomplete.

Also, if I clear the Persist and Reset flags on the capsule,
the immediate processing of the capsule does not work.

Is there any FW code that will look for capsules on disk?

If there are incomplete features in CapsuleApp, then I think
we should remove them.

Mike

> -----Original Message-----
> From: Yao, Jiewen
> Sent: Tuesday, September 20, 2016 11:45 PM
> To: edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org%3cmailto:edk2-devel@lists.01.org>>
> Cc: Tian, Feng <feng.tian@intel.com<mailto:feng.tian@intel.com<mailto:feng.tian@intel.com%3cmailto:feng.tian@intel.com>>>; Zeng, Star <star.zeng@intel.com<mailto:star.zeng@intel.com<mailto:star.zeng@intel.com%3cmailto:star.zeng@intel.com>>>; Kinney, Michael
> D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com%3cmailto:michael.d.kinney@intel.com>>>; Gao, Liming <liming.gao@intel.com<mailto:liming.gao@intel.com<mailto:liming.gao@intel.com%3cmailto:liming.gao@intel.com>>>; Zhang, Chao B
> <chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com%3cmailto:chao.b.zhang@intel.com>>>
> Subject: [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application.
>
> This CapsuleApp can help perform capsule update in UEFI shell environment.
> It can also dump capsule information, capsule status variable, ESRT and FMP.
>
> Cc: Feng Tian <feng.tian@intel.com<mailto:feng.tian@intel.com<mailto:feng.tian@intel.com%3cmailto:feng.tian@intel.com>>>
> Cc: Star Zeng <star.zeng@intel.com<mailto:star.zeng@intel.com<mailto:star.zeng@intel.com%3cmailto:star.zeng@intel.com>>>
> Cc: Michael D Kinney <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com%3cmailto:michael.d.kinney@intel.com>>>
> Cc: Liming Gao <liming.gao@intel.com<mailto:liming.gao@intel.com<mailto:liming.gao@intel.com%3cmailto:liming.gao@intel.com>>>
> Cc: Chao Zhang <chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com%3cmailto:chao.b.zhang@intel.com>>>
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Jiewen Yao <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com<mailto:jiewen.yao@intel.com%3cmailto:jiewen.yao@intel.com>>>
> ---
>  MdeModulePkg/Application/CapsuleApp/AppSupport.c        |  480 +++++++++
>  MdeModulePkg/Application/CapsuleApp/CapsuleApp.c        | 1047 ++++++++++++++++++++
>  MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf      |   71 ++
>  MdeModulePkg/Application/CapsuleApp/CapsuleApp.uni      |   22 +
>  MdeModulePkg/Application/CapsuleApp/CapsuleAppExtra.uni |   19 +
>  MdeModulePkg/Application/CapsuleApp/CapsuleDump.c       |  840 ++++++++++++++++
>  6 files changed, 2479 insertions(+)
>
> diff --git a/MdeModulePkg/Application/CapsuleApp/AppSupport.c
> b/MdeModulePkg/Application/CapsuleApp/AppSupport.c
> new file mode 100644
> index 0000000..365067d
> --- /dev/null
> +++ b/MdeModulePkg/Application/CapsuleApp/AppSupport.c
> @@ -0,0 +1,480 @@
> +/** @file
> +  A shell application that triggers capsule update process.
> +
> +  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the BSD License
> +  which accompanies this distribution.  The full text of the license may be found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +
> +**/
> +
> +#include <Uefi.h>
> +#include <Library/BaseLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/UefiRuntimeServicesTableLib.h>
> +#include <Library/UefiLib.h>
> +#include <Library/PrintLib.h>
> +#include <Protocol/LoadedImage.h>
> +#include <Protocol/SimpleFileSystem.h>
> +#include <Guid/FileInfo.h>
> +#include <Guid/Gpt.h>
> +
> +#define MAX_ARG_NUM     11
> +
> +UINTN  Argc = 0;
> +CHAR16 *Argv[MAX_ARG_NUM];
> +CHAR16 *ArgBuffer;
> +
> +/**
> +
> +  This function parse application ARG.
> +
> +  @return Status
> +**/
> +EFI_STATUS
> +GetArg (
> +  VOID
> +  )
> +{
> +  UINT8                         *Data;
> +  UINTN                         DataSize;
> +  CHAR16                        *Index;
> +  CHAR16                        *End;
> +  CHAR16                        *DIndex;
> +  EFI_STATUS                    Status;
> +  EFI_LOADED_IMAGE_PROTOCOL     *LoadedImage;
> +
> +  Status = gBS->HandleProtocol (
> +                  gImageHandle,
> +                  &gEfiLoadedImageProtocolGuid,
> +                  (VOID**)&LoadedImage
> +                  );
> +  if (EFI_ERROR(Status)) {
> +    return Status;
> +  }
> +
> +  Data = LoadedImage->LoadOptions;
> +  DataSize = LoadedImage->LoadOptionsSize;
> +
> +  End = (CHAR16*)(UINTN)(Data + DataSize);
> +  Status = gBS->AllocatePool (EfiBootServicesData, DataSize, (VOID **)&ArgBuffer);
> +  ASSERT_EFI_ERROR (Status);
> +  DIndex = ArgBuffer;
> +  Argv[Argc++] = ArgBuffer;
> +  for (Index = (CHAR16*)Data; Index < End; ) {
> +    if (*Index == L' ') {
> +      *DIndex = L'\0';
> +      if (Argc >= MAX_ARG_NUM) {
> +        return EFI_UNSUPPORTED;
> +      }
> +      Argv[Argc++] = (++ DIndex);
> +      while(*Index == L' ') {
> +        Index ++;
> +      }
> +    }
> +    (*(DIndex ++)) = (*(Index ++));
> +  }
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Clear APP ARG.
> +**/
> +VOID
> +CleanArg (
> +  VOID
> +  )
> +{
> +  FreePool (Argv[0]);
> +}
> +
> +/**
> +  Return File System Volume containing this shell application.
> +
> +  @return File System Volume containing this shell application.
> +**/
> +EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *
> +GetMyVol (
> +  VOID
> +  )
> +{
> +  EFI_STATUS                        Status;
> +  EFI_LOADED_IMAGE_PROTOCOL         *LoadedImage;
> +  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Vol;
> +
> +  Status = gBS->HandleProtocol (
> +                  gImageHandle,
> +                  &gEfiLoadedImageProtocolGuid,
> +                  (VOID **)&LoadedImage
> +                  );
> +  ASSERT_EFI_ERROR (Status);
> +
> +  Status = gBS->HandleProtocol (
> +                  LoadedImage->DeviceHandle,
> +                  &gEfiSimpleFileSystemProtocolGuid,
> +                  (VOID **)&Vol
> +                  );
> +  if (!EFI_ERROR (Status)) {
> +    return Vol;
> +  }
> +
> +  return NULL;
> +}
> +
> +/**
> +  Read a file from this volume.
> +
> +  @param Vol             File System Volume
> +  @param FileName        The file to be read.
> +  @param BufferSize      The file buffer size
> +  @param Buffer          The file buffer
> +
> +  @retval EFI_SUCCESS    Read file successfully
> +  @retval EFI_NOT_FOUND  File not found
> +**/
> +EFI_STATUS
> +ReadFileFromVol (
> +  IN  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Vol,
> +  IN  CHAR16                            *FileName,
> +  OUT UINTN                             *BufferSize,
> +  OUT VOID                              **Buffer
> +  )
> +{
> +  EFI_STATUS                        Status;
> +  EFI_FILE_HANDLE                   RootDir;
> +  EFI_FILE_HANDLE                   Handle;
> +  UINTN                             FileInfoSize;
> +  EFI_FILE_INFO                     *FileInfo;
> +  UINTN                             TempBufferSize;
> +  VOID                              *TempBuffer;
> +
> +  //
> +  // Open the root directory
> +  //
> +  Status = Vol->OpenVolume (Vol, &RootDir);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  //
> +  // Open the file
> +  //
> +  Status = RootDir->Open (
> +                      RootDir,
> +                      &Handle,
> +                      FileName,
> +                      EFI_FILE_MODE_READ,
> +                      0
> +                      );
> +  if (EFI_ERROR (Status)) {
> +    RootDir->Close (RootDir);
> +    return Status;
> +  }
> +
> +  RootDir->Close (RootDir);
> +
> +  //
> +  // Get the file information
> +  //
> +  FileInfoSize = sizeof(EFI_FILE_INFO) + 1024;
> +
> +  FileInfo = AllocateZeroPool (FileInfoSize);
> +  if (FileInfo == NULL) {
> +    Handle->Close (Handle);
> +    return Status;
> +  }
> +
> +  Status = Handle->GetInfo (
> +                     Handle,
> +                     &gEfiFileInfoGuid,
> +                     &FileInfoSize,
> +                     FileInfo
> +                     );
> +  if (EFI_ERROR (Status)) {
> +    Handle->Close (Handle);
> +    gBS->FreePool (FileInfo);
> +    return Status;
> +  }
> +
> +  //
> +  // Allocate buffer for the file data. The last CHAR16 is for L'\0'
> +  //
> +  TempBufferSize = (UINTN) FileInfo->FileSize + sizeof(CHAR16);
> +  TempBuffer = AllocateZeroPool (TempBufferSize);
> +  if (TempBuffer == NULL) {
> +    Handle->Close (Handle);
> +    gBS->FreePool (FileInfo);
> +    return Status;
> +  }
> +
> +  gBS->FreePool (FileInfo);
> +
> +  //
> +  // Read the file data to the buffer
> +  //
> +  Status = Handle->Read (
> +                     Handle,
> +                     &TempBufferSize,
> +                     TempBuffer
> +                     );
> +  if (EFI_ERROR (Status)) {
> +    Handle->Close (Handle);
> +    gBS->FreePool (TempBuffer);
> +    return Status;
> +  }
> +
> +  Handle->Close (Handle);
> +
> +  *BufferSize = TempBufferSize;
> +  *Buffer     = TempBuffer;
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Read a file.
> +  If ScanFs is FLASE, it will use this Vol as default Fs.
> +  If ScanFs is TRUE, it will scan all FS and check the file.
> +    If there is only one file match the name, it will be read.
> +    If there is more than one file match the name, it will return Error.
> +
> +  @param ThisVol         File System Volume
> +  @param FileName        The file to be read.
> +  @param BufferSize      The file buffer size
> +  @param Buffer          The file buffer
> +  @param ScanFs          Need Scan all FS
> +
> +  @retval EFI_SUCCESS    Read file successfully
> +  @retval EFI_NOT_FOUND  File not found
> +  @retval EFI_NO_MAPPING There is duplicated files found
> +**/
> +EFI_STATUS
> +ReadFileToBufferEx (
> +  IN OUT EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   **ThisVol,
> +  IN  CHAR16                               *FileName,
> +  OUT UINTN                                *BufferSize,
> +  OUT VOID                                 **Buffer,
> +  IN  BOOLEAN                              ScanFs
> +  )
> +{
> +  EFI_STATUS                        Status;
> +  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Vol;
> +  UINTN                             TempBufferSize;
> +  VOID                              *TempBuffer;
> +  UINTN                             NoHandles;
> +  EFI_HANDLE                        *HandleBuffer;
> +  UINTN                             Index;
> +
> +  //
> +  // Check parameters
> +  //
> +  if ((FileName == NULL) || (Buffer == NULL) || (ThisVol == NULL)) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  //
> +  // not scan fs
> +  //
> +  if (!ScanFs) {
> +    if (*ThisVol == NULL) {
> +      *ThisVol = GetMyVol ();
> +      if (*ThisVol == NULL) {
> +        return EFI_INVALID_PARAMETER;
> +      }
> +    }
> +    //
> +    // Read file directly from Vol
> +    //
> +    return ReadFileFromVol (*ThisVol, FileName, BufferSize, Buffer);
> +  }
> +
> +  //
> +  // need scan fs
> +  //
> +
> +  //
> +  // Get all Vol handle
> +  //
> +  Status = gBS->LocateHandleBuffer (
> +                   ByProtocol,
> +                   &gEfiSimpleFileSystemProtocolGuid,
> +                   NULL,
> +                   &NoHandles,
> +                   &HandleBuffer
> +                   );
> +  if (EFI_ERROR (Status) && (NoHandles == 0)) {
> +    return EFI_NOT_FOUND;
> +  }
> +
> +  //
> +  // Walk through each Vol
> +  //
> +  *ThisVol = NULL;
> +  *BufferSize = 0;
> +  *Buffer     = NULL;
> +  for (Index = 0; Index < NoHandles; Index++) {
> +    Status = gBS->HandleProtocol (
> +                    HandleBuffer[Index],
> +                    &gEfiSimpleFileSystemProtocolGuid,
> +                    (VOID **)&Vol
> +                    );
> +    if (EFI_ERROR(Status)) {
> +      continue;
> +    }
> +
> +    Status = ReadFileFromVol (Vol, FileName, &TempBufferSize, &TempBuffer);
> +    if (!EFI_ERROR (Status)) {
> +      //
> +      // Read file OK, check duplication
> +      //
> +      if (*ThisVol != NULL) {
> +        //
> +        // Find the duplicated file
> +        //
> +        gBS->FreePool (TempBuffer);
> +        gBS->FreePool (*Buffer);
> +        Print (L"Duplicated FileName found!\n");
> +        return EFI_NO_MAPPING;
> +      } else {
> +        //
> +        // Record value
> +        //
> +        *ThisVol = Vol;
> +        *BufferSize = TempBufferSize;
> +        *Buffer     = TempBuffer;
> +      }
> +    }
> +  }
> +
> +  //
> +  // Scan Fs done
> +  //
> +  if (*ThisVol == NULL) {
> +    return EFI_NOT_FOUND;
> +  }
> +
> +  //
> +  // Done
> +  //
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Read a file.
> +
> +  @param FileName        The file to be read.
> +  @param BufferSize      The file buffer size
> +  @param Buffer          The file buffer
> +
> +  @retval EFI_SUCCESS    Read file successfully
> +  @retval EFI_NOT_FOUND  File not found
> +**/
> +EFI_STATUS
> +ReadFileToBuffer (
> +  IN  CHAR16                               *FileName,
> +  OUT UINTN                                *BufferSize,
> +  OUT VOID                                 **Buffer
> +  )
> +{
> +  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Vol;
> +  Vol = NULL;
> +  return ReadFileToBufferEx(&Vol, FileName, BufferSize, Buffer, FALSE);
> +}
> +
> +/**
> +  Write a file.
> +
> +  @param FileName        The file to be written.
> +  @param BufferSize      The file buffer size
> +  @param Buffer          The file buffer
> +
> +  @retval EFI_SUCCESS    Write file successfully
> +**/
> +EFI_STATUS
> +WriteFileFromBuffer(
> +  IN  CHAR16                               *FileName,
> +  IN  UINTN                                BufferSize,
> +  IN  VOID                                 *Buffer
> +  )
> +{
> +  EFI_STATUS                        Status;
> +  EFI_FILE_HANDLE                   RootDir;
> +  EFI_FILE_HANDLE                   Handle;
> +  UINTN                             TempBufferSize;
> +  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Vol;
> +
> +  Vol = GetMyVol();
> +
> +  //
> +  // Open the root directory
> +  //
> +  Status = Vol->OpenVolume (Vol, &RootDir);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  //
> +  // Open the file
> +  //
> +  Status = RootDir->Open (
> +                      RootDir,
> +                      &Handle,
> +                      FileName,
> +                      EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE| EFI_FILE_MODE_CREATE,
> +                      0
> +                      );
> +  if (EFI_ERROR (Status)) {
> +    RootDir->Close (RootDir);
> +    return Status;
> +  }
> +
> +  //
> +  // Delete file
> +  //
> +  Status = Handle->Delete(Handle);
> +  if (EFI_ERROR(Status)) {
> +    return Status;
> +  }
> +
> +  //
> +  // Open the file again
> +  //
> +  Status = RootDir->Open (
> +                      RootDir,
> +                      &Handle,
> +                      FileName,
> +                      EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE| EFI_FILE_MODE_CREATE,
> +                      0
> +                      );
> +  if (EFI_ERROR (Status)) {
> +    RootDir->Close (RootDir);
> +    return Status;
> +  }
> +
> +  RootDir->Close (RootDir);
> +
> +  //
> +  // Write the file data from the buffer
> +  //
> +  TempBufferSize = BufferSize;
> +  Status = Handle->Write (
> +                     Handle,
> +                     &TempBufferSize,
> +                     Buffer
> +                     );
> +  if (EFI_ERROR (Status)) {
> +    Handle->Close (Handle);
> +    return Status;
> +  }
> +
> +  Handle->Close (Handle);
> +
> +  return EFI_SUCCESS;
> +}
> +
> diff --git a/MdeModulePkg/Application/CapsuleApp/CapsuleApp.c
> b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.c
> new file mode 100644
> index 0000000..0a28557
> --- /dev/null
> +++ b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.c
> @@ -0,0 +1,1047 @@
> +/** @file
> +  A shell application that triggers capsule update process.
> +
> +  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the BSD License
> +  which accompanies this distribution.  The full text of the license may be found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +
> +**/
> +
> +#include <Uefi.h>
> +#include <Library/BaseLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/UefiRuntimeServicesTableLib.h>
> +#include <Library/UefiLib.h>
> +#include <Library/PrintLib.h>
> +#include <Protocol/LoadedImage.h>
> +#include <Protocol/SimpleFileSystem.h>
> +#include <Protocol/GraphicsOutput.h>
> +#include <Guid/FileInfo.h>
> +#include <Guid/Gpt.h>
> +#include <Guid/GlobalVariable.h>
> +#include <Guid/CapsuleReport.h>
> +#include <Guid/SystemResourceTable.h>
> +#include <Guid/FmpCapsule.h>
> +#include <IndustryStandard/WindowsUxCapsule.h>
> +
> +#define CAPSULE_HEADER_SIZE  0x20
> +
> +#define NESTED_CAPSULE_HEADER_SIZE  SIZE_4KB
> +#define SYSTEM_FIRMWARE_FLAG 0x50000
> +#define DEVICE_FIRMWARE_FLAG 0x78010
> +
> +#define EFI_CAPSULE_FROM_FILE_DIR                           L"\\EFI\\UpdateCapsule\\<file:///\\EFI\UpdateCapsule\><file://EFI/UpdateCapsule/%3cfile:/EFI/UpdateCapsule/%3e>"
> +#define EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED  0x0000000000000004
> +
> +#define MAJOR_VERSION   1
> +#define MINOR_VERSION   0
> +
> +#define MAX_ARG_NUM     11
> +#define MAX_CAPSULE_NUM (MAX_ARG_NUM - 1)
> +
> +extern UINTN  Argc;
> +extern CHAR16 *Argv[];
> +
> +//
> +// Define how many block descriptors we want to test with.
> +//
> +UINTN  NumberOfDescriptors = 1;
> +UINTN  CapsuleFirstIndex;
> +UINTN  CapsuleLastIndex;
> +
> +/**
> +  Dump capsule information
> +
> +  @retval EFI_SUCCESS            The capsule information is dumped.
> +  @retval EFI_UNSUPPORTED        Input parameter is not valid.
> +**/
> +EFI_STATUS
> +DumpCapsule(
> +  VOID
> +  );
> +
> +/**
> +  Dump capsule status variable.
> +
> +  @retval EFI_SUCCESS            The capsule status variable is dumped.
> +  @retval EFI_UNSUPPORTED        Input parameter is not valid.
> +**/
> +EFI_STATUS
> +DmpCapsuleStatusVariable(
> +  VOID
> +  );
> +
> +/**
> +  Dump FMP protocol info.
> +**/
> +VOID
> +DumpFmpData(
> +  VOID
> +  );
> +
> +/**
> +  Dump ESRT info.
> +**/
> +VOID
> +DumpEsrtData(
> +  VOID
> +  );
> +
> +/**
> +  Read a file.
> +
> +  @param FileName        The file to be read.
> +  @param BufferSize      The file buffer size
> +  @param Buffer          The file buffer
> +
> +  @retval EFI_SUCCESS    Read file successfully
> +  @retval EFI_NOT_FOUND  File not found
> +**/
> +EFI_STATUS
> +ReadFileToBuffer(
> +  IN  CHAR16                               *FileName,
> +  OUT UINTN                                *BufferSize,
> +  OUT VOID                                 **Buffer
> +  );
> +
> +/**
> +  Write a file.
> +
> +  @param FileName        The file to be written.
> +  @param BufferSize      The file buffer size
> +  @param Buffer          The file buffer
> +
> +  @retval EFI_SUCCESS    Write file successfully
> +**/
> +EFI_STATUS
> +WriteFileFromBuffer(
> +  IN  CHAR16                               *FileName,
> +  IN  UINTN                                BufferSize,
> +  IN  VOID                                 *Buffer
> +  );
> +
> +/**
> +
> +  This function parse application ARG.
> +
> +  @return Status
> +**/
> +EFI_STATUS
> +GetArg (
> +  VOID
> +  );
> +
> +/**
> +  Clear APP ARG.
> +**/
> +VOID
> +CleanArg (
> +  VOID
> +  );
> +
> +/**
> +  Create UX capsule.
> +
> +  @retval EFI_SUCCESS            The capsule header is appended.
> +  @retval EFI_UNSUPPORTED        Input parameter is not valid.
> +  @retval EFI_OUT_OF_RESOURCES   No enough resource to create UX capsule.
> +**/
> +EFI_STATUS
> +CreateBmpFmp(
> +  VOID
> +  )
> +{
> +  CHAR16                                        *OutputCapsuleName;
> +  VOID                                          *BmpBuffer;
> +  UINTN                                         FileSize;
> +  CHAR16                                        *BmpName;
> +  UINT8                                         *FullCapsuleBuffer;
> +  UINTN                                         FullCapsuleBufferSize;
> +  EFI_DISPLAY_CAPSULE                           *DisplayCapsule;
> +  EFI_STATUS                                    Status;
> +  EFI_GRAPHICS_OUTPUT_PROTOCOL                  *Gop;
> +
> +  Status = gBS->LocateProtocol(&gEfiGraphicsOutputProtocolGuid, NULL, (VOID **)&Gop);
> +  if (EFI_ERROR(Status)) {
> +    Print(L"CapsuleApp: NO GOP is found.\n");
> +    return EFI_UNSUPPORTED;
> +  }
> +  Print(L"Current GOP: Mode - %d, ", Gop->Mode->Mode);
> +  Print(L"HorizontalResolution - %d, ", Gop->Mode->Info->HorizontalResolution);
> +  Print(L"VerticalResolution - %d\n", Gop->Mode->Info->VerticalResolution);
> +  // HorizontalResolution >= BMP_IMAGE_HEADER.PixelWidth
> +  // VerticalResolution   >= BMP_IMAGE_HEADER.PixelHeight
> +
> +  if (Argc != 5) {
> +    Print(L"CapsuleApp: Invalid Parameter.\n");
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  if (StrCmp(Argv[3], L"-O") != 0) {
> +    Print(L"CapsuleApp: NO output capsule name.\n");
> +    return EFI_UNSUPPORTED;
> +  }
> +  OutputCapsuleName = Argv[4];
> +
> +  BmpBuffer = NULL;
> +  FileSize = 0;
> +  FullCapsuleBuffer = NULL;
> +
> +  BmpName = Argv[2];
> +  Status = ReadFileToBuffer(BmpName, &FileSize, &BmpBuffer);
> +  if (EFI_ERROR(Status)) {
> +    Print(L"CapsuleApp: BMP image (%s) is not found.\n", BmpName);
> +    goto Done;
> +  }
> +
> +  FullCapsuleBufferSize = sizeof(EFI_DISPLAY_CAPSULE) + FileSize;
> +  FullCapsuleBuffer = AllocatePool(FullCapsuleBufferSize);
> +  if (FullCapsuleBuffer == NULL) {
> +    Print(L"CapsuleApp: Capsule Buffer size (0x%x) too big.\n",
> FullCapsuleBufferSize);
> +    Status = EFI_OUT_OF_RESOURCES;
> +    goto Done;
> +  }
> +
> +  DisplayCapsule = (EFI_DISPLAY_CAPSULE *)FullCapsuleBuffer;
> +  CopyGuid(&DisplayCapsule->CapsuleHeader.CapsuleGuid, &gWindowsUxCapsuleGuid);
> +  DisplayCapsule->CapsuleHeader.HeaderSize = sizeof(DisplayCapsule->CapsuleHeader);
> +  DisplayCapsule->CapsuleHeader.Flags = CAPSULE_FLAGS_PERSIST_ACROSS_RESET;
> +  DisplayCapsule->CapsuleHeader.CapsuleImageSize = (UINT32)FullCapsuleBufferSize;
> +
> +  DisplayCapsule->ImagePayload.Version = 1;
> +  DisplayCapsule->ImagePayload.Checksum = 0;
> +  DisplayCapsule->ImagePayload.ImageType = 0; // BMP
> +  DisplayCapsule->ImagePayload.Reserved = 0;
> +  DisplayCapsule->ImagePayload.Mode = Gop->Mode->Mode;
> +  DisplayCapsule->ImagePayload.OffsetX = 0;
> +  DisplayCapsule->ImagePayload.OffsetY = 0;
> +
> +  CopyMem((DisplayCapsule + 1), BmpBuffer, FileSize);
> +
> +  DisplayCapsule->ImagePayload.Checksum = CalculateCheckSum8(FullCapsuleBuffer,
> FullCapsuleBufferSize);
> +
> +  Status = WriteFileFromBuffer(OutputCapsuleName, FullCapsuleBufferSize,
> FullCapsuleBuffer);
> +  Print(L"CapsuleApp: Write %s %r\n", OutputCapsuleName, Status);
> +
> +Done:
> +  if (BmpBuffer != NULL) {
> +    FreePool(BmpBuffer);
> +  }
> +
> +  if (FullCapsuleBuffer != NULL) {
> +    FreePool(FullCapsuleBuffer);
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  Get ImageTypeId in the FMP capsule header.
> +
> +  @param CapsuleHeader  The FMP capsule image header.
> +
> +  @return ImageTypeId
> +**/
> +EFI_GUID *
> +GetCapsuleImageTypeId(
> +  IN EFI_CAPSULE_HEADER                            *CapsuleHeader
> +  )
> +{
> +  EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER       *FmpCapsuleHeader;
> +  UINT64                                       *ItemOffsetList;
> +  EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader;
> +
> +  FmpCapsuleHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *)((UINT8 *)CapsuleHeader
> + CapsuleHeader->HeaderSize);
> +  ItemOffsetList = (UINT64 *)(FmpCapsuleHeader + 1);
> +  if (FmpCapsuleHeader->PayloadItemCount == 0) {
> +    return NULL;
> +  }
> +  ImageHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *)((UINT8
> *)FmpCapsuleHeader + ItemOffsetList[FmpCapsuleHeader->EmbeddedDriverCount]);
> +  return &ImageHeader->UpdateImageTypeId;
> +}
> +
> +/**
> +  Get ESRT FwType according to ImageTypeId
> +
> +  @param  ImageTypeId   ImageTypeId of an FMP capsule.
> +
> +  @return ESRT FwType
> +**/
> +UINT32
> +GetEsrtFwType(
> +  IN  EFI_GUID                                      *ImageTypeId
> +  )
> +{
> +  EFI_STATUS                 Status;
> +  EFI_SYSTEM_RESOURCE_TABLE  *Esrt;
> +  EFI_SYSTEM_RESOURCE_ENTRY  *EsrtEntry;
> +  UINTN                      Index;
> +
> +  //
> +  // Check ESRT
> +  //
> +  Status = EfiGetSystemConfigurationTable(&gEfiSystemResourceTableGuid, (VOID
> **)&Esrt);
> +  if (!EFI_ERROR(Status)) {
> +    EsrtEntry = (VOID *)(Esrt + 1);
> +    for (Index = 0; Index < Esrt->FwResourceCount; Index++, EsrtEntry++) {
> +      if (CompareGuid(&EsrtEntry->FwClass, ImageTypeId)) {
> +        return EsrtEntry->FwType;
> +      }
> +    }
> +  }
> +
> +  return ESRT_FW_TYPE_UNKNOWN;
> +}
> +
> +/**
> +  Append a capsule header on top of current image.
> +  This function follows Windows UEFI Firmware Update Platform document.
> +
> +  @retval EFI_SUCCESS            The capsule header is appended.
> +  @retval EFI_UNSUPPORTED        Input parameter is not valid.
> +  @retval EFI_OUT_OF_RESOURCES   No enough resource to append capsule header.
> +**/
> +EFI_STATUS
> +CreateNestedFmp(
> +  VOID
> +  )
> +{
> +  CHAR16                                        *OutputCapsuleName;
> +  VOID                                          *CapsuleBuffer;
> +  UINTN                                         FileSize;
> +  CHAR16                                        *CapsuleName;
> +  UINT8                                         *FullCapsuleBuffer;
> +  UINTN                                         FullCapsuleBufferSize;
> +  EFI_CAPSULE_HEADER                            *NestedCapsuleHeader;
> +  EFI_GUID                                      *ImageTypeId;
> +  UINT32                                        FwType;
> +  EFI_STATUS                                    Status;
> +
> +  if (Argc != 5) {
> +    Print(L"CapsuleApp: Invalid Parameter.\n");
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  if (StrCmp(Argv[3], L"-O") != 0) {
> +    Print(L"CapsuleApp: NO output capsule name.\n");
> +    return EFI_UNSUPPORTED;
> +  }
> +  OutputCapsuleName = Argv[4];
> +
> +  CapsuleBuffer = NULL;
> +  FileSize = 0;
> +  FullCapsuleBuffer = NULL;
> +
> +  CapsuleName = Argv[2];
> +  Status = ReadFileToBuffer(CapsuleName, &FileSize, &CapsuleBuffer);
> +  if (EFI_ERROR(Status)) {
> +    Print(L"CapsuleApp: Capsule image (%s) is not found.\n", CapsuleName);
> +    goto Done;
> +  }
> +
> +  ImageTypeId = GetCapsuleImageTypeId(CapsuleBuffer);
> +  if (ImageTypeId == NULL) {
> +    Print(L"CapsuleApp: Capsule ImageTypeId is not found.\n");
> +    goto Done;
> +  }
> +  FwType = GetEsrtFwType(ImageTypeId);
> +  if ((FwType != ESRT_FW_TYPE_SYSTEMFIRMWARE) && (FwType !=
> ESRT_FW_TYPE_DEVICEFIRMWARE)) {
> +    Print(L"CapsuleApp: Capsule FwType is invalid.\n");
> +    goto Done;
> +  }
> +
> +  FullCapsuleBufferSize = NESTED_CAPSULE_HEADER_SIZE + FileSize;
> +  FullCapsuleBuffer = AllocatePool(FullCapsuleBufferSize);
> +  if (FullCapsuleBuffer == NULL) {
> +    Print(L"CapsuleApp: Capsule Buffer size (0x%x) too big.\n",
> FullCapsuleBufferSize);
> +    Status = EFI_OUT_OF_RESOURCES;
> +    goto Done;
> +  }
> +
> +  NestedCapsuleHeader = (EFI_CAPSULE_HEADER *)FullCapsuleBuffer;
> +  ZeroMem(NestedCapsuleHeader, NESTED_CAPSULE_HEADER_SIZE);
> +  CopyGuid(&NestedCapsuleHeader->CapsuleGuid, ImageTypeId);
> +  NestedCapsuleHeader->HeaderSize = NESTED_CAPSULE_HEADER_SIZE;
> +  NestedCapsuleHeader->Flags = (FwType == ESRT_FW_TYPE_DEVICEFIRMWARE) ?
> SYSTEM_FIRMWARE_FLAG : DEVICE_FIRMWARE_FLAG;
> +  NestedCapsuleHeader->CapsuleImageSize = (UINT32)FullCapsuleBufferSize;
> +
> +  CopyMem((UINT8 *)NestedCapsuleHeader + NestedCapsuleHeader->HeaderSize,
> CapsuleBuffer, FileSize);
> +
> +  Status = WriteFileFromBuffer(OutputCapsuleName, FullCapsuleBufferSize,
> FullCapsuleBuffer);
> +  Print(L"CapsuleApp: Write %s %r\n", OutputCapsuleName, Status);
> +
> +Done:
> +  if (CapsuleBuffer != NULL) {
> +    FreePool(CapsuleBuffer);
> +  }
> +
> +  if (FullCapsuleBuffer != NULL) {
> +    FreePool(FullCapsuleBuffer);
> +  }
> +
> +  return Status;
> +}
> +
> +
> +/**
> +  Clear capsule status variable.
> +
> +  @retval EFI_SUCCESS            The capsule status variable is cleared.
> +**/
> +EFI_STATUS
> +ClearCapsuleStatusVariable(
> +  VOID
> +  )
> +{
> +  EFI_STATUS                          Status;
> +  UINT32                              Index;
> +  CHAR16                              CapsuleVarName[20];
> +  CHAR16                              *TempVarName;
> +
> +  StrCpyS (CapsuleVarName, sizeof(CapsuleVarName)/sizeof(CapsuleVarName[0]),
> L"Capsule");
> +  TempVarName = CapsuleVarName + StrLen (CapsuleVarName);
> +  Index = 0;
> +
> +  while (TRUE) {
> +    UnicodeSPrint (TempVarName, 5 * sizeof(CHAR16), L"%04x", Index);
> +
> +    Status = gRT->SetVariable (
> +                    CapsuleVarName,
> +                    &gEfiCapsuleReportGuid,
> +                    EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS |
> EFI_VARIABLE_BOOTSERVICE_ACCESS,
> +                    0,
> +                    (VOID *)NULL
> +                    );
> +    if (EFI_ERROR(Status)) {
> +      //
> +      // There is no capsule variables, quit
> +      //
> +      break;
> +    }
> +
> +    Index++;
> +    if (Index > 0xFFFF) {
> +      break;
> +    }
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Get the active UEFI system partition from bootoption list.
> +
> +  @param[out] Fs    Simple File System protocol on the active UEFI system partition
> +
> +  @retval EFI_SUCCESS   active UEFI system partition found
> +**/
> +EFI_STATUS
> +GetEfiSysPartition(
> +  OUT EFI_SIMPLE_FILE_SYSTEM_PROTOCOL **Fs
> +  )
> +{
> +  EFI_STATUS                       Status;
> +  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL  *FsTemp;
> +  UINTN                            NoHandles;
> +  EFI_HANDLE                       *Handles;
> +  UINTN                            Index;
> +
> +  Handles = NULL;
> +
> +  //
> +  // search for EFI system partition protocol on Boot option device path
> +  //
> +  Status = gBS->LocateHandleBuffer(ByProtocol, &gEfiPartTypeSystemPartGuid, NULL,
> &NoHandles, &Handles);
> +  if (EFI_ERROR(Status)) {
> +    return Status;
> +  }
> +
> +  //
> +  // Skip BootOptions within FV
> +  //
> +  for (Index = 0; Index < NoHandles; Index++) {
> +    Status = gBS->HandleProtocol (Handles[Index], &gEfiSimpleFileSystemProtocolGuid,
> (VOID **)&FsTemp);
> +    if (!EFI_ERROR (Status)){
> +      *Fs = FsTemp;
> +      break;
> +    }
> +  }
> +  return Status;
> +}
> +
> +/**
> +  Copy a list of capsule images to the active UEFI system partition from bootoption
> list.
> +
> +  @param[in] CapsuleBuffer    An array of pointer to capsule images
> +  @param[in] FileSize         An array of UINTN to capsule images size
> +  @param[in] CapsuleNum       The count of capsule images
> +
> +  @retval EFI_SUCCESS   Capsule images are copied to the active UEFI system partition
> +**/
> +EFI_STATUS
> +CopyCapsuleToActiveEfiPartition(
> +  IN VOID                          **CapsuleBuffer,
> +  IN UINTN                         *FileSize,
> +  IN UINTN                         CapsuleNum
> +  )
> +{
> +  EFI_STATUS                       Status;
> +  CHAR16                           *CapsuleName;
> +  UINTN                            Index;
> +  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL  *Fs;
> +  EFI_FILE_HANDLE                  RootDir;
> +  EFI_FILE_HANDLE                  CapsuleDir;
> +  EFI_FILE_HANDLE                  DestHandle;
> +  UINTN                            DataSize;
> +  UINT64                           OsIndication;
> +
> +  RootDir      = NULL;
> +  CapsuleDir   = NULL;
> +
> +  Status = GetEfiSysPartition(&Fs);
> +  if (EFI_ERROR(Status)) {
> +    Print (L"Can not find active UEFI System Partition\n");
> +    return Status;
> +  }
> +
> +  Status = Fs->OpenVolume(Fs, &RootDir);
> +  if (EFI_ERROR(Status)) {
> +    goto EXIT;
> +  }
> +
> +  Status = RootDir->Open(
> +                      RootDir,
> +                      &CapsuleDir,
> +                      EFI_CAPSULE_FROM_FILE_DIR,
> +                      EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE,
> +                      EFI_FILE_DIRECTORY
> +                      );
> +  if (EFI_ERROR(Status)) {
> +    goto EXIT;
> +  }
> +
> +  //
> +  // Read the input files.
> +  //
> +  for (Index = 0; Index < CapsuleNum; Index++) {
> +    CapsuleName = Argv[CapsuleFirstIndex + Index];
> +    Status = CapsuleDir->Open(
> +                           CapsuleDir,
> +                           &DestHandle,
> +                           CapsuleName,
> +                           EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE |
> EFI_FILE_MODE_CREATE,
> +                           EFI_FILE_ARCHIVE
> +                           );
> +    if (EFI_ERROR(Status)) {
> +      Print(L"CapsuleApp: %s open error - %r\n", CapsuleName, Status);
> +      continue;
> +    }
> +
> +    DataSize = FileSize[Index];
> +    Status = DestHandle->Write(
> +                           DestHandle,
> +                           &DataSize,
> +                           CapsuleBuffer[Index]
> +                           );
> +    DestHandle->Close(DestHandle);
> +    if (EFI_ERROR(Status)) {
> +      Print(L"CapsuleApp: %s write error - %r, FileSize - 0x%x\n", CapsuleName,
> Status, FileSize[Index]);
> +    }
> +  }
> +
> +  Status = gRT->GetVariable (
> +                  L"OsIndications",
> +                  &gEfiGlobalVariableGuid,
> +                  NULL,
> +                  &DataSize,
> +                  (VOID *) &OsIndication
> +                  );
> +
> +  if (EFI_ERROR(Status) || DataSize != sizeof(OsIndication)) {
> +    OsIndication = 0;
> +  }
> +
> +  //
> +  // Set OsIndications Variable EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED bit
> +  //
> +  OsIndication |= EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED;
> +  Status = gRT->SetVariable (
> +                  L"OsIndications",
> +                  &gEfiGlobalVariableGuid,
> +                  EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS |
> +                  EFI_VARIABLE_BOOTSERVICE_ACCESS,
> +                  sizeof(OsIndication),
> +                  (VOID *)&OsIndication
> +                  );
> +
> +
> +EXIT:
> +  if (RootDir != NULL) {
> +    RootDir->Close(RootDir);
> +  }
> +
> +  if (CapsuleDir != NULL) {
> +    CapsuleDir->Close(CapsuleDir);
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  Build Gather list for a list of capsule images.
> +
> +  @param[in]  CapsuleBuffer    An array of pointer to capsule images
> +  @param[in]  FileSize         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                         *FileSize,
> +  IN UINTN                         CapsuleNum,
> +  OUT EFI_CAPSULE_BLOCK_DESCRIPTOR **BlockDescriptors
> +  )
> +{
> +  EFI_STATUS                    Status;
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR  *BlockDescriptors1;
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR  *BlockDescriptors2;
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR  *BlockDescriptorPre;
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR  *BlockDescriptorsHeader;
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR  *TempBlockPtr;
> +  UINT8                         *TempDataPtr;
> +  UINTN                         SizeLeft;
> +  UINTN                         Size;
> +  INT32                         Count;
> +  INT32                         Number;
> +  UINTN                         Index;
> +
> +  TempBlockPtr           = NULL;
> +  BlockDescriptors1      = NULL;
> +  BlockDescriptors2      = NULL;
> +  BlockDescriptorPre     = NULL;
> +  BlockDescriptorsHeader = NULL;
> +
> +  for (Index = 0; Index < CapsuleNum; Index++) {
> +    //
> +    // Allocate memory for the descriptors.
> +    //
> +    if (NumberOfDescriptors == 1) {
> +      Count = 2;
> +    } else {
> +      Count = (INT32)(NumberOfDescriptors + 2) / 2;
> +    }
> +
> +    Size               = Count * sizeof (EFI_CAPSULE_BLOCK_DESCRIPTOR);
> +    BlockDescriptors1  = AllocateRuntimeZeroPool (Size);
> +    if (BlockDescriptors1 == NULL) {
> +      Print (L"CapsuleApp: failed to allocate memory for descriptors\n");
> +      Status = EFI_OUT_OF_RESOURCES;
> +      goto ERREXIT;
> +    } else {
> +      Print (L"CapsuleApp: creating capsule descriptors at 0x%X\n", (UINTN)
> BlockDescriptors1);
> +      Print (L"CapsuleApp: capsule data starts          at 0x%X with size 0x%X\n",
> (UINTN) CapsuleBuffer, FileSize);
> +    }
> +
> +    //
> +    // Record descirptor header
> +    //
> +    if (Index == 0) {
> +      BlockDescriptorsHeader = BlockDescriptors1;
> +    }
> +
> +    if (BlockDescriptorPre != NULL) {
> +      BlockDescriptorPre->Union.ContinuationPointer = (UINTN) BlockDescriptors1;
> +      BlockDescriptorPre->Length = 0;
> +    }
> +
> +    //
> +    // Fill them in
> +    //
> +    TempBlockPtr  = BlockDescriptors1;
> +    TempDataPtr   = CapsuleBuffer[Index];
> +    SizeLeft      = FileSize[Index];
> +    for (Number = 0; (Number < Count - 1) && (SizeLeft != 0); Number++) {
> +      //
> +      // Divide remaining data in half
> +      //
> +      if (NumberOfDescriptors != 1) {
> +        if (SizeLeft == 1) {
> +          Size = 1;
> +        } else {
> +          Size = SizeLeft / 2;
> +        }
> +      } else {
> +        Size = SizeLeft;
> +      }
> +      TempBlockPtr->Union.DataBlock    = (UINTN)TempDataPtr;
> +      TempBlockPtr->Length  = Size;
> +      Print (L"CapsuleApp: capsule block/size              0x%X/0x%X\n", (UINTN)
> TempDataPtr, Size);
> +      SizeLeft -= Size;
> +      TempDataPtr += Size;
> +      TempBlockPtr++;
> +    }
> +
> +    //
> +    // Allocate the second list, point the first block's last entry to point
> +    // to this one, and fill this one in. Worst case is that the previous
> +    // list only had one element that pointed here, so we need at least two
> +    // elements -- one to point to all the data, another to terminate the list.
> +    //
> +    if ((NumberOfDescriptors != 1) && (SizeLeft != 0)) {
> +      Count = (INT32)(NumberOfDescriptors + 2) - Count;
> +      if (Count == 1) {
> +        Count++;
> +      }
> +
> +      Size              = Count * sizeof (EFI_CAPSULE_BLOCK_DESCRIPTOR);
> +      BlockDescriptors2 = AllocateRuntimeZeroPool (Size);
> +      if (BlockDescriptors2 == NULL) {
> +        Print (L"CapsuleApp: failed to allocate memory for descriptors\n");
> +        Status = EFI_OUT_OF_RESOURCES;
> +        goto ERREXIT;
> +      }
> +
> +      //
> +      // Point the first list's last element to point to this second list.
> +      //
> +      TempBlockPtr->Union.ContinuationPointer   = (UINTN) BlockDescriptors2;
> +
> +      TempBlockPtr->Length  = 0;
> +      TempBlockPtr = BlockDescriptors2;
> +      for (Number = 0; Number < Count - 1; Number++) {
> +        //
> +        // If second-to-last one, then dump rest to this element
> +        //
> +        if (Number == (Count - 2)) {
> +          Size = SizeLeft;
> +        } else {
> +          //
> +          // Divide remaining data in half
> +          //
> +          if (SizeLeft == 1) {
> +            Size = 1;
> +          } else {
> +            Size = SizeLeft / 2;
> +          }
> +        }
> +
> +        TempBlockPtr->Union.DataBlock    = (UINTN)TempDataPtr;
> +        TempBlockPtr->Length  = Size;
> +        Print (L"CapsuleApp: capsule block/size              0x%X/0x%X\n", (UINTN)
> TempDataPtr, Size);
> +        SizeLeft -= Size;
> +        TempDataPtr += Size;
> +        TempBlockPtr++;
> +        if (SizeLeft == 0) {
> +          break;
> +        }
> +      }
> +    }
> +
> +    BlockDescriptorPre = TempBlockPtr;
> +    BlockDescriptors1  = NULL;
> +  }
> +
> +  //
> +  // Null-terminate.
> +  //
> +  if (TempBlockPtr != NULL) {
> +    TempBlockPtr->Union.ContinuationPointer    = (UINTN)NULL;
> +    TempBlockPtr->Length  = 0;
> +    *BlockDescriptors = BlockDescriptorsHeader;
> +  }
> +
> +  return EFI_SUCCESS;
> +
> +ERREXIT:
> +  if (BlockDescriptors1 != NULL) {
> +    FreePool(BlockDescriptors1);
> +  }
> +
> +  if (BlockDescriptors2 != NULL) {
> +    FreePool(BlockDescriptors2);
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  Clear the Gather list for a list of capsule images.
> +
> +  @param[in]  BlockDescriptors The block descriptors for the capsule images
> +  @param[in]  CapsuleNum       The count of capsule images
> +**/
> +VOID
> +CleanGatherList(
> +  IN EFI_CAPSULE_BLOCK_DESCRIPTOR   *BlockDescriptors,
> +  IN UINTN                          CapsuleNum
> +  )
> +{
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR   *TempBlockPtr;
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR   *TempBlockPtr1;
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR   *TempBlockPtr2;
> +  UINTN                          Index;
> +
> +  if (BlockDescriptors != NULL) {
> +    TempBlockPtr1 = BlockDescriptors;
> +    while (1){
> +      TempBlockPtr = TempBlockPtr1;
> +      for (Index = 0; Index < CapsuleNum; Index++) {
> +        if (TempBlockPtr[Index].Length == 0) {
> +          break;
> +        }
> +      }
> +
> +      if (TempBlockPtr[Index].Union.ContinuationPointer == (UINTN)NULL) {
> +        break;
> +      }
> +
> +      TempBlockPtr2 = (VOID *) ((UINTN) TempBlockPtr->Union.ContinuationPointer);
> +      FreePool(TempBlockPtr1);
> +      TempBlockPtr1 = TempBlockPtr2;
> +    }
> +  }
> +}
> +
> +/**
> +  Print APP usage.
> +**/
> +VOID
> +PrintUsage (
> +  VOID
> +  )
> +{
> +  Print(L"CapsuleApp:  usage\n");
> +  Print(L"  CapsuleApp [-F] <Capsule...> [-NR]\n");
> +  Print(L"  CapsuleApp -S\n");
> +  Print(L"  CapsuleApp -C\n");
> +  Print(L"  CapsuleApp -P\n");
> +  Print(L"  CapsuleApp -E\n");
> +  Print(L"  CapsuleApp -G <BMP> -O <Capsule>\n");
> +  Print(L"  CapsuleApp -N <Capsule> -O <NestedCapsule>\n");
> +  Print(L"  CapsuleApp -D|-DS <Capsule>\n");
> +  Print(L"Parameter:\n");
> +  Print(L"  -F:  Put capsule file to disk.\n");
> +  Print(L"       No -F means to put capsule file in memory.\n");
> +  Print(L"  -NR: No Reset.\n");
> +  Print(L"  -S:  Dump capsule status.\n");
> +  Print(L"  -C:  Clear capsule status.\n");
> +  Print(L"  -P:  Dump FMP protocol info.\n");
> +  Print(L"  -E:  Dump ESRT table info.\n");
> +  Print(L"  -G:  Input BMP file name\n");
> +  Print(L"  -N:  Append Capsule Header accroding to Windows Firmware Update\n");
> +  Print(L"  -O:  Output Capsule file name\n");
> +  Print(L"  -D:  Dump Capsule\n");
> +  Print(L"  -DS: Dump Capsule with System FMP format\n");
> +}
> +
> +/**
> +  Update Capsule image.
> +
> +  @param[in]  ImageHandle     The image handle.
> +  @param[in]  SystemTable     The system table.
> +
> +  @retval EFI_SUCCESS            Command completed successfully.
> +  @retval EFI_INVALID_PARAMETER  Command usage error.
> +  @retval EFI_NOT_FOUND          The input file can't be found.
> +**/
> +EFI_STATUS
> +EFIAPI
> +UefiMain (
> +  IN EFI_HANDLE        ImageHandle,
> +  IN EFI_SYSTEM_TABLE  *SystemTable
> +  )
> +{
> +  EFI_STATUS                    Status;
> +  UINTN                         FileSize[MAX_CAPSULE_NUM];
> +  VOID                          *CapsuleBuffer[MAX_CAPSULE_NUM];
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR  *BlockDescriptors;
> +  EFI_CAPSULE_HEADER             *CapsuleHeaderArray[MAX_CAPSULE_NUM + 1];
> +  UINT64                         MaxCapsuleSize;
> +  EFI_RESET_TYPE                 ResetType;
> +  BOOLEAN                        NeedReset;
> +  BOOLEAN                        NoReset;
> +  BOOLEAN                        NeedCopyOnDisk;
> +  CHAR16                         *CapsuleName;
> +  UINTN                          CapsuleNum;
> +  UINTN                          Index;
> +
> +  Status = GetArg();
> +  if (EFI_ERROR(Status)) {
> +    PrintUsage();
> +    return Status;
> +  }
> +  if (Argc < 2) {
> +    PrintUsage();
> +    CleanArg();
> +    return EFI_INVALID_PARAMETER;
> +  }
> +  if ((StrCmp(Argv[1], L"-D") == 0) ||
> +      (StrCmp(Argv[1], L"-DS") == 0)) {
> +    Status = DumpCapsule();
> +    CleanArg();
> +    return Status;
> +  }
> +  if (StrCmp(Argv[1], L"-G") == 0) {
> +    Status = CreateBmpFmp();
> +    CleanArg();
> +    return Status;
> +  }
> +  if (StrCmp(Argv[1], L"-N") == 0) {
> +    Status = CreateNestedFmp();
> +    CleanArg();
> +    return Status;
> +  }
> +  if (StrCmp(Argv[1], L"-S") == 0) {
> +    Status = DmpCapsuleStatusVariable();
> +    CleanArg();
> +    return EFI_SUCCESS;
> +  }
> +  if (StrCmp(Argv[1], L"-C") == 0) {
> +    Status = ClearCapsuleStatusVariable();
> +    CleanArg();
> +    return Status;
> +  }
> +  if (StrCmp(Argv[1], L"-P") == 0) {
> +    DumpFmpData();
> +    CleanArg();
> +    return EFI_SUCCESS;
> +  }
> +  if (StrCmp(Argv[1], L"-E") == 0) {
> +    DumpEsrtData();
> +    CleanArg();
> +    return EFI_SUCCESS;
> +  }
> +  if (StrCmp(Argv[1], L"-F") == 0) {
> +    NeedCopyOnDisk = TRUE;
> +    CapsuleFirstIndex = 2;
> +  } else {
> +    NeedCopyOnDisk = FALSE;
> +    CapsuleFirstIndex = 1;
> +  }
> +  if (StrCmp(Argv[Argc - 1], L"-NR") == 0) {
> +    NoReset = TRUE;
> +    CapsuleLastIndex = Argc - 2;
> +  } else {
> +    NoReset = FALSE;
> +    CapsuleLastIndex = Argc - 1;
> +  }
> +  CapsuleNum = CapsuleLastIndex - CapsuleFirstIndex + 1;
> +
> +  if (CapsuleFirstIndex > CapsuleLastIndex) {
> +    Print(L"CapsuleApp: NO capsule image.\n");
> +    CleanArg();
> +    return EFI_UNSUPPORTED;
> +  }
> +  if (CapsuleNum > MAX_CAPSULE_NUM) {
> +    Print(L"CapsuleApp: Too many capsule images.\n");
> +    CleanArg();
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  ZeroMem(&CapsuleBuffer, sizeof(CapsuleBuffer));
> +  ZeroMem(&FileSize, sizeof(FileSize));
> +  BlockDescriptors = NULL;
> +
> +  for (Index = 0; Index < CapsuleNum; Index++) {
> +    CapsuleName = Argv[CapsuleFirstIndex + Index];
> +    Status = ReadFileToBuffer(CapsuleName, &FileSize[Index], &CapsuleBuffer[Index]);
> +    if (EFI_ERROR(Status)) {
> +      Print(L"CapsuleApp: capsule image (%s) is not found.\n", CapsuleName);
> +      goto Done;
> +    }
> +  }
> +
> +  if (NeedCopyOnDisk) {
> +    Status = CopyCapsuleToActiveEfiPartition(CapsuleBuffer, FileSize, CapsuleNum);
> +  } else {
> +    //
> +    // Every capsule use 2 descriptor 1 for data 1 for end
> +    //
> +    Status = BuildGatherList(CapsuleBuffer, FileSize, CapsuleNum, &BlockDescriptors);
> +  }
> +  if (EFI_ERROR(Status)) {
> +    goto Done;
> +  }
> +
> +  //
> +  // Call the runtime service capsule.
> +  //
> +  NeedReset = FALSE;
> +  for (Index = 0; Index < CapsuleNum; Index++) {
> +    CapsuleHeaderArray[Index] = (EFI_CAPSULE_HEADER *) CapsuleBuffer[Index];
> +    if ((CapsuleHeaderArray[Index]->Flags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET) != 0)
> {
> +      NeedReset = TRUE;
> +    }
> +  }
> +  CapsuleHeaderArray[CapsuleNum] = NULL;
> +  if (NoReset) {
> +    NeedReset = FALSE;
> +  }
> +
> +  //
> +  // Inquire platform capability of UpdateCapsule.
> +  //
> +  Status = gRT->QueryCapsuleCapabilities (CapsuleHeaderArray, CapsuleNum,
> &MaxCapsuleSize, &ResetType);
> +  if (EFI_ERROR(Status)) {
> +    Print (L"CapsuleApp: failed to query capsule capability - %r\n", Status);
> +    goto Done;
> +  }
> +
> +  for (Index = 0; Index < CapsuleNum; Index++) {
> +    if (FileSize[Index] > MaxCapsuleSize) {
> +      Print (L"CapsuleApp: capsule is too large to update, %ld is allowed\n",
> MaxCapsuleSize);
> +      Status = EFI_UNSUPPORTED;
> +      goto Done;
> +    }
> +  }
> +
> +  //
> +  // Check whether the input capsule image has the flag of persist across system
> reset.
> +  //
> +  if (NeedReset) {
> +    Status = gRT->UpdateCapsule(CapsuleHeaderArray,CapsuleNum,(UINTN)
> BlockDescriptors);
> +    if (Status != EFI_SUCCESS) {
> +      Print (L"CapsuleApp: failed to update capsule - %r\n", Status);
> +      goto Done;
> +    }
> +    //
> +    // For capsule who has reset flag, after calling UpdateCapsule service,triger a
> +    // system reset to process capsule persist across a system reset.
> +    //
> +    gRT->ResetSystem (ResetType, EFI_SUCCESS, 0, NULL);
> +  } else {
> +    //
> +    // For capsule who has no reset flag, only call UpdateCapsule Service without a
> +    // system reset. The service will process the capsule immediately.
> +    //
> +    Status = gRT->UpdateCapsule (CapsuleHeaderArray,CapsuleNum,(UINTN)
> BlockDescriptors);
> +    if (Status != EFI_SUCCESS) {
> +      Print (L"CapsuleApp: failed to update capsule - %r\n", Status);
> +    }
> +  }
> +
> +  Status = EFI_SUCCESS;
> +
> +Done:
> +  for (Index = 0; Index < CapsuleNum; Index++) {
> +    if (CapsuleBuffer[Index] != NULL) {
> +      FreePool (CapsuleBuffer[Index]);
> +    }
> +  }
> +
> +  CleanGatherList(BlockDescriptors, CapsuleNum);
> +  CleanArg();
> +
> +  return Status;
> +}
> diff --git a/MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf
> b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf
> new file mode 100644
> index 0000000..7ee44fc
> --- /dev/null
> +++ b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf
> @@ -0,0 +1,71 @@
> +##  @file
> +#  A shell application that triggers capsule update process.
> +#
> +# This application can trigger capsule update process. It can also
> +# generate capsule image, or dump capsule variable information.
> +#
> +#  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
> +#  This program and the accompanying materials
> +#  are licensed and made available under the terms and conditions of the BSD License
> +#  which accompanies this distribution.  The full text of the license may be found at
> +#  http://opensource.org/licenses/bsd-license.php
> +#
> +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +#
> +##
> +
> +[Defines]
> +  INF_VERSION                    = 0x00010006
> +  BASE_NAME                      = CapsuleApp
> +  MODULE_UNI_FILE                = CapsuleApp.uni
> +  FILE_GUID                      = 4CEF31DA-8682-4274-9CC4-AEE7516A5E7B
> +  MODULE_TYPE                    = UEFI_APPLICATION
> +  VERSION_STRING                 = 1.0
> +  ENTRY_POINT                    = UefiMain
> +
> +#
> +# The following information is for reference only and not required by the build tools.
> +#
> +#  VALID_ARCHITECTURES           = IA32 X64
> +#
> +
> +[Sources]
> +  CapsuleApp.c
> +  CapsuleDump.c
> +  AppSupport.c
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +
> +[Guids]
> +  gEfiFileInfoGuid
> +  gEfiPartTypeSystemPartGuid
> +  gEfiGlobalVariableGuid
> +  gEfiCapsuleReportGuid
> +  gEfiFmpCapsuleGuid
> +  gWindowsUxCapsuleGuid
> +  gEfiCertTypeRsa2048Sha256Guid
> +  gEfiCertPkcs7Guid
> +  gEfiSystemResourceTableGuid
> +
> +[Protocols]
> +  gEfiLoadedImageProtocolGuid
> +  gEfiSimpleFileSystemProtocolGuid
> +  gEfiGraphicsOutputProtocolGuid
> +  gEfiFirmwareManagementProtocolGuid
> +
> +[LibraryClasses]
> +  BaseLib
> +  UefiApplicationEntryPoint
> +  DebugLib
> +  MemoryAllocationLib
> +  UefiBootServicesTableLib
> +  UefiRuntimeServicesTableLib
> +  UefiLib
> +  PrintLib
> +  EdkiiSystemCapsuleLib
> +
> +[UserExtensions.TianoCore."ExtraFiles"]
> +  CapsuleAppExtra.uni
> diff --git a/MdeModulePkg/Application/CapsuleApp/CapsuleApp.uni
> b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.uni
> new file mode 100644
> index 0000000..54d6e12
> --- /dev/null
> +++ b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.uni
> @@ -0,0 +1,22 @@
> +// /** @file
> +// A shell application that triggers capsule update process.
> +//
> +// This application can trigger capsule update process. It can also
> +// generate capsule image, or dump capsule variable information.
> +//
> +// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
> +//
> +// This program and the accompanying materials
> +// are licensed and made available under the terms and conditions of the BSD License
> +// which accompanies this distribution. The full text of the license may be found at
> +// http://opensource.org/licenses/bsd-license.php
> +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +//
> +// **/
> +
> +
> +#string STR_MODULE_ABSTRACT             #language en-US "A shell application that
> triggers capsule update process."
> +
> +#string STR_MODULE_DESCRIPTION          #language en-US "This application can trigger
> capsule update process. It can also generate capsule image, or dump capsule variable
> information."
> +
> diff --git a/MdeModulePkg/Application/CapsuleApp/CapsuleAppExtra.uni
> b/MdeModulePkg/Application/CapsuleApp/CapsuleAppExtra.uni
> new file mode 100644
> index 0000000..b5a8840
> --- /dev/null
> +++ b/MdeModulePkg/Application/CapsuleApp/CapsuleAppExtra.uni
> @@ -0,0 +1,19 @@
> +// /** @file
> +// CapsuleApp Localized Strings and Content
> +//
> +// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
> +//
> +// This program and the accompanying materials
> +// are licensed and made available under the terms and conditions of the BSD License
> +// which accompanies this distribution. The full text of the license may be found at
> +// http://opensource.org/licenses/bsd-license.php
> +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +//
> +// **/
> +
> +#string STR_PROPERTIES_MODULE_NAME
> +#language en-US
> +"Capsule Application"
> +
> +
> diff --git a/MdeModulePkg/Application/CapsuleApp/CapsuleDump.c
> b/MdeModulePkg/Application/CapsuleApp/CapsuleDump.c
> new file mode 100644
> index 0000000..c56f41f
> --- /dev/null
> +++ b/MdeModulePkg/Application/CapsuleApp/CapsuleDump.c
> @@ -0,0 +1,840 @@
> +/** @file
> +  Dump Capsule image information.
> +
> +  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the BSD License
> +  which accompanies this distribution.  The full text of the license may be found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +
> +**/
> +
> +#include <PiDxe.h>
> +#include <Library/BaseLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/UefiRuntimeServicesTableLib.h>
> +#include <Library/UefiLib.h>
> +#include <Library/PrintLib.h>
> +#include <Library/EdkiiSystemCapsuleLib.h>
> +#include <Protocol/FirmwareManagement.h>
> +#include <Guid/ImageAuthentication.h>
> +#include <Guid/EdkiiSystemFmpCapsule.h>
> +#include <Guid/CapsuleReport.h>
> +#include <Guid/SystemResourceTable.h>
> +#include <Guid/FmpCapsule.h>
> +#include <IndustryStandard/WindowsUxCapsule.h>
> +
> +/**
> +  Read a file.
> +
> +  @param FileName        The file to be read.
> +  @param BufferSize      The file buffer size
> +  @param Buffer          The file buffer
> +
> +  @retval EFI_SUCCESS    Read file successfully
> +  @retval EFI_NOT_FOUND  File not found
> +**/
> +EFI_STATUS
> +ReadFileToBuffer(
> +  IN  CHAR16                               *FileName,
> +  OUT UINTN                                *BufferSize,
> +  OUT VOID                                 **Buffer
> +  );
> +
> +extern UINTN  Argc;
> +extern CHAR16 *Argv[];
> +
> +/**
> +  Dump UX capsule information.
> +
> +  @param CapsuleHeader      The UX capsule header
> +**/
> +VOID
> +DumpUxCapsule(
> +  IN EFI_CAPSULE_HEADER  *CapsuleHeader
> +  )
> +{
> +  EFI_DISPLAY_CAPSULE                           *DisplayCapsule;
> +  DisplayCapsule = (EFI_DISPLAY_CAPSULE *)CapsuleHeader;
> +  Print(L"[UxCapusule]\n");
> +  Print(L"CapsuleHeader:\n");
> +  Print(L"  CapsuleGuid      - %g\n", &DisplayCapsule->CapsuleHeader.CapsuleGuid);
> +  Print(L"  HeaderSize       - 0x%x\n", DisplayCapsule->CapsuleHeader.HeaderSize);
> +  Print(L"  Flags            - 0x%x\n", DisplayCapsule->CapsuleHeader.Flags);
> +  Print(L"  CapsuleImageSize - 0x%x\n", DisplayCapsule-
> >CapsuleHeader.CapsuleImageSize);
> +  Print(L"ImagePayload:\n");
> +  Print(L"  Version          - 0x%x\n", DisplayCapsule->ImagePayload.Version);
> +  Print(L"  Checksum         - 0x%x\n", DisplayCapsule->ImagePayload.Checksum);
> +  Print(L"  ImageType        - 0x%x\n", DisplayCapsule->ImagePayload.ImageType);
> +  Print(L"  Mode             - 0x%x\n", DisplayCapsule->ImagePayload.Mode);
> +  Print(L"  OffsetX          - 0x%x\n", DisplayCapsule->ImagePayload.OffsetX);
> +  Print(L"  OffsetY          - 0x%x\n", DisplayCapsule->ImagePayload.OffsetY);
> +}
> +
> +/**
> +  Dump FMP image authentication information.
> +
> +  @param Image      The FMP capsule image
> +  @param ImageSize  The size of the FMP capsule image in bytes.
> +
> +  @return the size of FMP authentication.
> +**/
> +UINTN
> +DumpImageAuthentication(
> +  IN VOID   *Image,
> +  IN UINTN  ImageSize
> +  )
> +{
> +  EFI_FIRMWARE_IMAGE_AUTHENTICATION             *ImageAuthentication;
> +
> +  ImageAuthentication = Image;
> +  if (CompareGuid(&ImageAuthentication->AuthInfo.CertType, &gEfiCertPkcs7Guid) ||
> +      CompareGuid(&ImageAuthentication->AuthInfo.CertType,
> &gEfiCertTypeRsa2048Sha256Guid)) {
> +    Print(L"[ImageAuthentication]\n");
> +    Print(L"  MonotonicCount   - 0x%lx\n", ImageAuthentication->MonotonicCount);
> +    Print(L"WIN_CERTIFICATE:\n");
> +    Print(L"  dwLength         - 0x%x\n", ImageAuthentication->AuthInfo.Hdr.dwLength);
> +    Print(L"  wRevision        - 0x%x\n", ImageAuthentication-
> >AuthInfo.Hdr.wRevision);
> +    Print(L"  wCertificateType - 0x%x\n", ImageAuthentication-
> >AuthInfo.Hdr.wCertificateType);
> +    Print(L"  CertType         - %g\n", &ImageAuthentication->AuthInfo.CertType);
> +    return sizeof(ImageAuthentication->MonotonicCount) + ImageAuthentication-
> >AuthInfo.Hdr.dwLength;
> +  } else {
> +    return 0;
> +  }
> +}
> +
> +/**
> +  Dump EDKII system FMP capsule.
> +
> +  @param Image      The EDKII system FMP capsule.
> +  @param ImageSize  The size of the EDKII system FMP capsule in bytes.
> +**/
> +VOID
> +DumpEdkiiSystemFmpCapsule(
> +  IN VOID   *Image,
> +  IN UINTN  ImageSize
> +  )
> +{
> +  UINTN                                         ImageOffset;
> +  VOID                                          *BiosImage;
> +  UINTN                                         BiosImageSize;
> +  BOOLEAN                                       Result;
> +  EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR        *TempImageFmpInfo;
> +  EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR        *ImageFmpInfo;
> +  UINTN                                         ImageFmpInfoSize;
> +
> +  //
> +  // We do not know if there is EFI_FIRMWARE_IMAGE_AUTHENTICATION.
> +  // so just *try* to parse it
> +  //
> +  ImageOffset = DumpImageAuthentication(Image, ImageSize);
> +  Image = (UINT8 *)Image + ImageOffset;
> +  ImageSize -= ImageOffset;
> +  Print(L"[Image]\n");
> +  Print(L"  ImageSize   - 0x%x\n", ImageSize);
> +
> +  Result = ExtractConfigImage(Image, ImageSize, &BiosImage, &BiosImageSize);
> +  if (Result) {
> +    Print(L"  ConfigFileSize  - 0x%x\n", BiosImageSize);
> +  }
> +  Result = ExtractDriverFvImage(Image, ImageSize, &BiosImage, &BiosImageSize);
> +  if (Result) {
> +    Print(L"  DriverFvSize    - 0x%x\n", BiosImageSize);
> +  }
> +  Result = ExtractSystemFirmwareImage(Image, ImageSize, &BiosImage, &BiosImageSize);
> +  if (Result) {
> +    Print(L"  BiosImageSize   - 0x%x\n", BiosImageSize);
> +  }
> +  Result = ExtractSystemFirmwareImageFmpInfo(BiosImage, BiosImageSize,
> &TempImageFmpInfo, &ImageFmpInfoSize);
> +  if (Result) {
> +    ImageFmpInfo = AllocateCopyPool(ImageFmpInfoSize, TempImageFmpInfo);
> +    if (ImageFmpInfo != NULL) {
> +      Print(L"[ImageFmpInfo]\n");
> +      Print(L"  Signature                      - 0x%x\n", ImageFmpInfo->Signature);
> +      Print(L"  HeaderLength                   - 0x%x\n", ImageFmpInfo->HeaderLength);
> +      Print(L"  Length                         - 0x%x\n", ImageFmpInfo->Length);
> +      Print(L"  PackageVersion                 - 0x%x\n", ImageFmpInfo-
> >PackageVersion);
> +      Print(L"  PackageVersionNameStringOffset - 0x%x\n", ImageFmpInfo-
> >PackageVersionNameStringOffset);
> +      if (ImageFmpInfo->PackageVersionNameStringOffset != 0) {
> +        Print(L"                                 - %s\n", (UINT8 *)ImageFmpInfo +
> ImageFmpInfo->PackageVersionNameStringOffset);
> +      }
> +      Print(L"  ImageIndex                     - 0x%x\n", ImageFmpInfo->ImageIndex);
> +      Print(L"  ImageTypeId                    - %g\n", &ImageFmpInfo->ImageTypeId);
> +      Print(L"  ImageId                        - 0x%lx\n", ImageFmpInfo->ImageId);
> +      Print(L"  ImageIdNameStringOffset        - 0x%x\n", ImageFmpInfo-
> >ImageIdNameStringOffset);
> +      if (ImageFmpInfo->ImageIdNameStringOffset != 0) {
> +        Print(L"                                 - %s\n", (UINT8 *)ImageFmpInfo +
> ImageFmpInfo->ImageIdNameStringOffset);
> +      }
> +      Print(L"  Version                        - 0x%x\n", ImageFmpInfo->Version);
> +      Print(L"  VersionNameStringOffset        - 0x%x\n", ImageFmpInfo-
> >VersionNameStringOffset);
> +      if (ImageFmpInfo->VersionNameStringOffset != 0) {
> +        Print(L"                                 - %s\n", (UINT8 *)ImageFmpInfo +
> ImageFmpInfo->VersionNameStringOffset);
> +      }
> +      Print(L"  Size                           - 0x%lx\n", ImageFmpInfo->Size);
> +      Print(L"  AttributesSupported            - 0x%lx\n", ImageFmpInfo-
> >AttributesSupported);
> +      Print(L"  AttributesSetting              - 0x%lx\n", ImageFmpInfo-
> >AttributesSetting);
> +      Print(L"  Compatibilities                - 0x%lx\n", ImageFmpInfo-
> >Compatibilities);
> +      Print(L"  LowestSupportedImageVersion    - 0x%x\n", ImageFmpInfo-
> >LowestSupportedImageVersion);
> +      Print(L"  LastAttemptVersion             - 0x%x\n", ImageFmpInfo-
> >LastAttemptVersion);
> +      Print(L"  LastAttemptStatus              - 0x%x\n", ImageFmpInfo-
> >LastAttemptStatus);
> +      Print(L"  HardwareInstance               - 0x%lx\n", ImageFmpInfo-
> >HardwareInstance);
> +      Print(L"  Version                        - 0x%x\n", ImageFmpInfo->Version);
> +      FreePool(ImageFmpInfo);
> +    }
> +  }
> +}
> +
> +/**
> +  Dump a non-nested FMP capsule.
> +
> +  @param  CapsuleHeader  A pointer to CapsuleHeader
> +  @param  IsSystemFmp    If it is a system FMP
> +**/
> +VOID
> +DumpFmpCapsule(
> +  IN EFI_CAPSULE_HEADER  *CapsuleHeader,
> +  IN BOOLEAN             IsSystemFmp
> +  )
> +{
> +  EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER        *FmpCapsuleHeader;
> +  UINT64                                        *ItemOffsetList;
> +  UINTN                                         Index;
> +  UINTN                                         Count;
> +  EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER  *FmpImageHeader;
> +  VOID                                          *Image;
> +
> +  Print(L"[FmpCapusule]\n");
> +  Print(L"CapsuleHeader:\n");
> +  Print(L"  CapsuleGuid      - %g\n", &CapsuleHeader->CapsuleGuid);
> +  Print(L"  HeaderSize       - 0x%x\n", CapsuleHeader->HeaderSize);
> +  Print(L"  Flags            - 0x%x\n", CapsuleHeader->Flags);
> +  Print(L"  CapsuleImageSize - 0x%x\n", CapsuleHeader->CapsuleImageSize);
> +
> +  FmpCapsuleHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *)((UINT8 *)CapsuleHeader
> + CapsuleHeader->HeaderSize);
> +  ItemOffsetList = (UINT64 *)(FmpCapsuleHeader + 1);
> +  Print(L"FmpHeader:\n");
> +  Print(L"  Version             - 0x%x\n", FmpCapsuleHeader->Version);
> +  Print(L"  EmbeddedDriverCount - 0x%x\n", FmpCapsuleHeader->EmbeddedDriverCount);
> +  Print(L"  PayloadItemCount    - 0x%x\n", FmpCapsuleHeader->PayloadItemCount);
> +  Count = FmpCapsuleHeader->EmbeddedDriverCount + FmpCapsuleHeader->PayloadItemCount;
> +  for (Index = 0; Index < Count; Index++) {
> +    Print(L"  Offset[%d]           - 0x%x\n", Index, ItemOffsetList[Index]);
> +  }
> +
> +  for (Index = FmpCapsuleHeader->EmbeddedDriverCount; Index < Count; Index++) {
> +    Print(L"FmpPayload[%d] ImageHeader:\n", Index);
> +    FmpImageHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *)((UINT8
> *)FmpCapsuleHeader + ItemOffsetList[Index]);
> +    Print(L"  Version                - 0x%x\n", FmpImageHeader->Version);
> +    Print(L"  UpdateImageTypeId      - %g\n", &FmpImageHeader->UpdateImageTypeId);
> +    Print(L"  UpdateImageIndex       - 0x%x\n", FmpImageHeader->UpdateImageIndex);
> +    Print(L"  UpdateImageSize        - 0x%x\n", FmpImageHeader->UpdateImageSize);
> +    Print(L"  UpdateVendorCodeSize   - 0x%x\n", FmpImageHeader->UpdateVendorCodeSize);
> +    if (FmpImageHeader->Version >=
> EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {
> +      Print(L"  UpdateHardwareInstance - 0x%lx\n", FmpImageHeader-
> >UpdateHardwareInstance);
> +    }
> +    if (FmpImageHeader->Version >=
> EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {
> +      Image = (UINT8 *)(FmpImageHeader + 1);
> +    }  else {
> +      Image = (UINT8 *)FmpImageHeader +
> OFFSET_OF(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER, UpdateHardwareInstance);
> +    }
> +    if (IsSystemFmp) {
> +      DumpEdkiiSystemFmpCapsule(Image, FmpImageHeader->UpdateImageSize);
> +    }
> +  }
> +}
> +
> +/**
> +  Return if there is a FMP header below capsule header.
> +
> +  @param[in] CapsuleHeader A pointer to EFI_CAPSULE_HEADER
> +
> +  @retval TRUE  There is a FMP header below capsule header.
> +  @retval FALSE There is not a FMP header below capsule header
> +**/
> +BOOLEAN
> +IsNestedFmpCapsule(
> +  IN EFI_CAPSULE_HEADER         *CapsuleHeader
> +  )
> +{
> +  EFI_STATUS                 Status;
> +  EFI_SYSTEM_RESOURCE_TABLE  *Esrt;
> +  EFI_SYSTEM_RESOURCE_ENTRY  *EsrtEntry;
> +  UINTN                      Index;
> +  BOOLEAN                    EsrtGuidFound;
> +  EFI_CAPSULE_HEADER         *NestedCapsuleHeader;
> +  UINTN                      NestedCapsuleSize;
> +
> +  //
> +  // Check ESRT
> +  //
> +  EsrtGuidFound = FALSE;
> +  Status = EfiGetSystemConfigurationTable(&gEfiSystemResourceTableGuid, (VOID
> **)&Esrt);
> +  if (!EFI_ERROR(Status)) {
> +    EsrtEntry = (VOID *)(Esrt + 1);
> +    for (Index = 0; Index < Esrt->FwResourceCount; Index++, EsrtEntry++) {
> +      if (CompareGuid(&EsrtEntry->FwClass, &CapsuleHeader->CapsuleGuid)) {
> +        EsrtGuidFound = TRUE;
> +        break;
> +      }
> +    }
> +  }
> +
> +  if (!EsrtGuidFound) {
> +    return FALSE;
> +  }
> +
> +  //
> +  // Check nested capsule header
> +  // FMP GUID after ESRT one
> +  //
> +  NestedCapsuleHeader = (EFI_CAPSULE_HEADER *)((UINT8 *)CapsuleHeader + CapsuleHeader-
> >HeaderSize);
> +  NestedCapsuleSize = (UINTN)CapsuleHeader + CapsuleHeader->HeaderSize -
> (UINTN)NestedCapsuleHeader;
> +  if (NestedCapsuleSize < sizeof(EFI_CAPSULE_HEADER)) {
> +    return FALSE;
> +  }
> +  if (!CompareGuid(&NestedCapsuleHeader->CapsuleGuid, &gEfiFmpCapsuleGuid)) {
> +    return FALSE;
> +  }
> +  return TRUE;
> +}
> +
> +/**
> +  Dump capsule information
> +
> +  @retval EFI_SUCCESS            The capsule information is dumped.
> +  @retval EFI_UNSUPPORTED        Input parameter is not valid.
> +**/
> +EFI_STATUS
> +DumpCapsule(
> +  VOID
> +  )
> +{
> +  CHAR16                                        *CapsuleName;
> +  VOID                                          *Buffer;
> +  UINTN                                         FileSize;
> +  BOOLEAN                                       IsSystemFmp;
> +  EFI_CAPSULE_HEADER                            *CapsuleHeader;
> +  EFI_STATUS                                    Status;
> +
> +  if (Argc != 3) {
> +    Print(L"CapsuleApp: Invalid Parameter.\n");
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  IsSystemFmp = FALSE;
> +  if (StrCmp(Argv[1], L"-DS") == 0) {
> +    IsSystemFmp = TRUE;
> +  }
> +
> +  CapsuleName = Argv[2];
> +  Status = ReadFileToBuffer(CapsuleName, &FileSize, &Buffer);
> +  if (EFI_ERROR(Status)) {
> +    Print(L"CapsuleApp: Capsule (%s) is not found.\n", CapsuleName);
> +    goto Done;
> +  }
> +
> +  CapsuleHeader = Buffer;
> +  if (CompareGuid(&CapsuleHeader->CapsuleGuid, &gWindowsUxCapsuleGuid)) {
> +    DumpUxCapsule(CapsuleHeader);
> +    Status = EFI_SUCCESS;
> +    goto Done;
> +  }
> +
> +  if (CompareGuid(&CapsuleHeader->CapsuleGuid, &gEfiFmpCapsuleGuid)) {
> +    DumpFmpCapsule(CapsuleHeader, IsSystemFmp);
> +  }
> +  if (IsNestedFmpCapsule(CapsuleHeader)) {
> +    Print(L"[NestedCapusule]\n");
> +    Print(L"CapsuleHeader:\n");
> +    Print(L"  CapsuleGuid      - %g\n", &CapsuleHeader->CapsuleGuid);
> +    Print(L"  HeaderSize       - 0x%x\n", CapsuleHeader->HeaderSize);
> +    Print(L"  Flags            - 0x%x\n", CapsuleHeader->Flags);
> +    Print(L"  CapsuleImageSize - 0x%x\n", CapsuleHeader->CapsuleImageSize);
> +    DumpFmpCapsule((EFI_CAPSULE_HEADER *)((UINTN)CapsuleHeader + CapsuleHeader-
> >HeaderSize), IsSystemFmp);
> +  }
> +
> +Done:
> +  FreePool(Buffer);
> +  return Status;
> +}
> +
> +/**
> +  Dump capsule status variable.
> +
> +  @retval EFI_SUCCESS            The capsule status variable is dumped.
> +  @retval EFI_UNSUPPORTED        Input parameter is not valid.
> +**/
> +EFI_STATUS
> +DmpCapsuleStatusVariable(
> +  VOID
> +  )
> +{
> +  EFI_STATUS                          Status;
> +  UINT32                              Index;
> +  CHAR16                              CapsuleVarName[20];
> +  CHAR16                              *TempVarName;
> +  EFI_CAPSULE_RESULT_VARIABLE_HEADER  *CapsuleResult;
> +  EFI_CAPSULE_RESULT_VARIABLE_FMP     *CapsuleResultFmp;
> +  UINTN                               CapsuleFileNameSize;
> +  CHAR16                              CapsuleIndexData[12];
> +  CHAR16                              *CapsuleIndex;
> +
> +  Status = GetVariable2(
> +             L"CapsuleMax",
> +             &gEfiCapsuleReportGuid,
> +             (VOID **)&CapsuleIndex,
> +             NULL
> +             );
> +  if (!EFI_ERROR(Status)) {
> +    CopyMem(CapsuleIndexData, CapsuleIndex, 11 * sizeof(CHAR16));
> +    CapsuleIndexData[11] = 0;
> +    Print(L"CapsuleMax - %s\n", CapsuleIndexData);
> +    FreePool(CapsuleIndex);
> +  }
> +  Status = GetVariable2(
> +             L"CapsuleLast",
> +             &gEfiCapsuleReportGuid,
> +             (VOID **)&CapsuleIndex,
> +             NULL
> +             );
> +  if (!EFI_ERROR(Status)) {
> +    CopyMem(CapsuleIndexData, CapsuleIndex, 11 * sizeof(CHAR16));
> +    CapsuleIndexData[11] = 0;
> +    Print(L"CapsuleLast - %s\n", CapsuleIndexData);
> +    FreePool(CapsuleIndex);
> +  }
> +
> +
> +  StrCpyS (CapsuleVarName, sizeof(CapsuleVarName)/sizeof(CapsuleVarName[0]),
> L"Capsule");
> +  TempVarName = CapsuleVarName + StrLen (CapsuleVarName);
> +  Index = 0;
> +
> +  while (TRUE) {
> +    UnicodeSPrint (TempVarName, 5 * sizeof(CHAR16), L"%04x", Index);
> +
> +    Status = GetVariable2 (
> +               CapsuleVarName,
> +               &gEfiCapsuleReportGuid,
> +               (VOID **) &CapsuleResult,
> +               NULL
> +               );
> +    if (Status == EFI_NOT_FOUND) {
> +      break;
> +    } else if (EFI_ERROR(Status)) {
> +      continue;
> +    }
> +
> +    //
> +    // display capsule process status
> +    //
> +    if (CapsuleResult->VariableTotalSize >=
> sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER)) {
> +      Print (L"CapsuleName: %s\n", CapsuleVarName);
> +      Print (L"  Capsule Guid: %g\n", &CapsuleResult->CapsuleGuid);
> +      Print (L"  Capsule ProcessedTime: %t\n", &CapsuleResult->CapsuleProcessed);
> +      Print (L"  Capsule Status: %r\n", CapsuleResult->CapsuleStatus);
> +    }
> +
> +    if (CompareGuid(&CapsuleResult->CapsuleGuid, &gEfiFmpCapsuleGuid)) {
> +      if (CapsuleResult->VariableTotalSize >=
> sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER) + sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP)) {
> +        CapsuleResultFmp = (EFI_CAPSULE_RESULT_VARIABLE_FMP *)(CapsuleResult + 1);
> +        Print(L"  Capsule FMP Version: 0x%x\n", CapsuleResultFmp->Version);
> +        Print(L"  Capsule FMP PayloadIndex: 0x%x\n", CapsuleResultFmp->PayloadIndex);
> +        Print(L"  Capsule FMP UpdateImageIndex: 0x%x\n", CapsuleResultFmp-
> >UpdateImageIndex);
> +        Print(L"  Capsule FMP UpdateImageTypeId: %g\n", &CapsuleResultFmp-
> >UpdateImageTypeId);
> +        if (CapsuleResult->VariableTotalSize >
> sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER) + sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP)) {
> +          Print(L"  Capsule FMP CapsuleFileName: %s\n", (CapsuleResultFmp + 1));
> +          CapsuleFileNameSize = StrSize((CHAR16 *)(CapsuleResultFmp + 1));
> +          if (CapsuleResult->VariableTotalSize >
> sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER) + sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP) +
> CapsuleFileNameSize) {
> +            Print(L"  Capsule FMP CapsuleTarget: %s\n", (UINT8 *)(CapsuleResultFmp +
> 1) + CapsuleFileNameSize);
> +          }
> +        }
> +      }
> +    }
> +
> +    FreePool(CapsuleResult);
> +
> +    Index++;
> +    if (Index > 0xFFFF) {
> +      break;
> +    }
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +CHAR8 *mFwTypeString[] = {
> +  "Unknown",
> +  "SystemFirmware",
> +  "DeviceFirmware",
> +  "UefiDriver",
> +};
> +
> +CHAR8 *mLastAttemptStatusString[] = {
> +  "Success",
> +  "Error: Unsuccessful",
> +  "Error: Insufficient Resources",
> +  "Error: Incorrect Version",
> +  "Error: Invalid Format",
> +  "Error: Auth Error",
> +  "Error: Power Event AC",
> +  "Error: Power Event Battery",
> +};
> +
> +/**
> +  Convert FwType to a string.
> +
> +  @param FwType  FwType in ESRT
> +
> +  @return a string for FwType.
> +**/
> +CHAR8 *
> +FwTypeToString(
> +  IN UINT32 FwType
> +  )
> +{
> +  if (FwType < sizeof(mFwTypeString) / sizeof(mFwTypeString[0])) {
> +    return mFwTypeString[FwType];
> +  } else {
> +    return "Invalid";
> +  }
> +}
> +
> +/**
> +  Convert LastAttemptStatus to a string.
> +
> +  @param LastAttemptStatus  LastAttemptStatus in FMP or ESRT
> +
> +  @return a string for LastAttemptStatus.
> +**/
> +CHAR8 *
> +LastAttemptStatusToString(
> +  IN UINT32 LastAttemptStatus
> +  )
> +{
> +  if (LastAttemptStatus < sizeof(mLastAttemptStatusString) /
> sizeof(mLastAttemptStatusString[0])) {
> +    return mLastAttemptStatusString[LastAttemptStatus];
> +  } else {
> +    return "Error: Unknown";
> +  }
> +}
> +
> +/**
> +  Dump ESRT entry.
> +
> +  @param EsrtEntry  ESRT entry
> +**/
> +VOID
> +DumpEsrtEntry(
> +  IN EFI_SYSTEM_RESOURCE_ENTRY  *EsrtEntry
> +  )
> +{
> +  Print(L"  FwClass                  - %g\n", &EsrtEntry->FwClass);
> +  Print(L"  FwType                   - 0x%x (%a)\n", EsrtEntry->FwType,
> FwTypeToString(EsrtEntry->FwType));
> +  Print(L"  FwVersion                - 0x%x\n", EsrtEntry->FwVersion);
> +  Print(L"  LowestSupportedFwVersion - 0x%x\n", EsrtEntry->LowestSupportedFwVersion);
> +  Print(L"  CapsuleFlags             - 0x%x\n", EsrtEntry->CapsuleFlags);
> +  Print(L"    PERSIST_ACROSS_RESET   - 0x%x\n", EsrtEntry->CapsuleFlags &
> CAPSULE_FLAGS_PERSIST_ACROSS_RESET);
> +  Print(L"    POPULATE_SYSTEM_TABLE  - 0x%x\n", EsrtEntry->CapsuleFlags &
> CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE);
> +  Print(L"    INITIATE_RESET         - 0x%x\n", EsrtEntry->CapsuleFlags &
> CAPSULE_FLAGS_INITIATE_RESET);
> +  Print(L"  LastAttemptVersion       - 0x%x\n", EsrtEntry->LastAttemptVersion);
> +  Print(L"  LastAttemptStatus        - 0x%x (%a)\n", EsrtEntry->LastAttemptStatus,
> LastAttemptStatusToString(EsrtEntry->LastAttemptStatus));
> +}
> +
> +/**
> +  Dump ESRT table.
> +
> +  @param Esrt  ESRT table
> +**/
> +VOID
> +DumpEsrt(
> +  IN EFI_SYSTEM_RESOURCE_TABLE  *Esrt
> +  )
> +{
> +  UINTN                      Index;
> +  EFI_SYSTEM_RESOURCE_ENTRY  *EsrtEntry;
> +
> +  Print(L"EFI_SYSTEM_RESOURCE_TABLE:\n");
> +  Print(L"FwResourceCount    - 0x%x\n", Esrt->FwResourceCount);
> +  Print(L"FwResourceCountMax - 0x%x\n", Esrt->FwResourceCountMax);
> +  Print(L"FwResourceVersion  - 0x%lx\n", Esrt->FwResourceVersion);
> +
> +  EsrtEntry = (VOID *)(Esrt + 1);
> +  for (Index = 0; Index < Esrt->FwResourceCount; Index++) {
> +    Print(L"EFI_SYSTEM_RESOURCE_ENTRY (%d):\n", Index);
> +    DumpEsrtEntry(EsrtEntry);
> +    EsrtEntry++;
> +  }
> +}
> +
> +/**
> +  Dump ESRT info.
> +**/
> +VOID
> +DumpEsrtData (
> +  VOID
> +  )
> +{
> +  EFI_STATUS                 Status;
> +  EFI_SYSTEM_RESOURCE_TABLE  *Esrt;
> +
> +  Print(L"##############\n");
> +  Print(L"# ESRT TABLE #\n");
> +  Print(L"##############\n");
> +
> +  Status = EfiGetSystemConfigurationTable (&gEfiSystemResourceTableGuid, (VOID
> **)&Esrt);
> +  if (EFI_ERROR(Status)) {
> +    Print(L"ESRT - %r\n", Status);
> +    return;
> +  }
> +  DumpEsrt(Esrt);
> +  Print(L"\n");
> +}
> +
> +/**
> +  Dump FMP information.
> +
> +  @param ImageInfoSize       The size of ImageInfo, in bytes.
> +  @param ImageInfo           A pointer to EFI_FIRMWARE_IMAGE_DESCRIPTOR.
> +  @param DescriptorVersion   The version of EFI_FIRMWARE_IMAGE_DESCRIPTOR.
> +  @param DescriptorCount     The count of EFI_FIRMWARE_IMAGE_DESCRIPTOR.
> +  @param DescriptorSize      The size of an individual EFI_FIRMWARE_IMAGE_DESCRIPTOR,
> in bytes.
> +  @param PackageVersion      The version of package.
> +  @param PackageVersionName  The version name of package.
> +**/
> +VOID
> +DumpFmpImageInfo(
> +  IN UINTN                           ImageInfoSize,
> +  IN EFI_FIRMWARE_IMAGE_DESCRIPTOR   *ImageInfo,
> +  IN UINT32                          DescriptorVersion,
> +  IN UINT8                           DescriptorCount,
> +  IN UINTN                           DescriptorSize,
> +  IN UINT32                          PackageVersion,
> +  IN CHAR16                          *PackageVersionName
> +  )
> +{
> +  EFI_FIRMWARE_IMAGE_DESCRIPTOR                 *CurrentImageInfo;
> +  UINTN                                         Index;
> +
> +  Print(L"  DescriptorVersion  - 0x%x\n", DescriptorVersion);
> +  Print(L"  DescriptorCount    - 0x%x\n", DescriptorCount);
> +  Print(L"  DescriptorSize     - 0x%x\n", DescriptorSize);
> +  Print(L"  PackageVersion     - 0x%x\n", PackageVersion);
> +  Print(L"  PackageVersionName - \"%s\"\n", PackageVersionName);
> +  CurrentImageInfo = ImageInfo;
> +  for (Index = 0; Index < DescriptorCount; Index++) {
> +    Print(L"  ImageDescriptor (%d)\n", Index);
> +    Print(L"    ImageIndex                  - 0x%x\n", CurrentImageInfo->ImageIndex);
> +    Print(L"    ImageTypeId                 - %g\n", &CurrentImageInfo->ImageTypeId);
> +    Print(L"    ImageId                     - 0x%lx\n", CurrentImageInfo->ImageId);
> +    Print(L"    ImageIdName                 - \"%s\"\n", CurrentImageInfo-
> >ImageIdName);
> +    Print(L"    Version                     - 0x%x\n", CurrentImageInfo->Version);
> +    Print(L"    VersionName                 - \"%s\"\n", CurrentImageInfo-
> >VersionName);
> +    Print(L"    Size                        - 0x%x\n", CurrentImageInfo->Size);
> +    Print(L"    AttributesSupported         - 0x%lx\n", CurrentImageInfo-
> >AttributesSupported);
> +    Print(L"      IMAGE_UPDATABLE           - 0x%lx\n", CurrentImageInfo-
> >AttributesSupported & IMAGE_ATTRIBUTE_IMAGE_UPDATABLE);
> +    Print(L"      RESET_REQUIRED            - 0x%lx\n", CurrentImageInfo-
> >AttributesSupported & IMAGE_ATTRIBUTE_RESET_REQUIRED);
> +    Print(L"      AUTHENTICATION_REQUIRED   - 0x%lx\n", CurrentImageInfo-
> >AttributesSupported & IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);
> +    Print(L"      IN_USE                    - 0x%lx\n", CurrentImageInfo-
> >AttributesSupported & IMAGE_ATTRIBUTE_IN_USE);
> +    Print(L"      UEFI_IMAGE                - 0x%lx\n", CurrentImageInfo-
> >AttributesSupported & IMAGE_ATTRIBUTE_UEFI_IMAGE);
> +    Print(L"    AttributesSetting           - 0x%lx\n", CurrentImageInfo-
> >AttributesSetting);
> +    Print(L"      IMAGE_UPDATABLE           - 0x%lx\n", CurrentImageInfo-
> >AttributesSetting & IMAGE_ATTRIBUTE_IMAGE_UPDATABLE);
> +    Print(L"      RESET_REQUIRED            - 0x%lx\n", CurrentImageInfo-
> >AttributesSetting & IMAGE_ATTRIBUTE_RESET_REQUIRED);
> +    Print(L"      AUTHENTICATION_REQUIRED   - 0x%lx\n", CurrentImageInfo-
> >AttributesSetting & IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);
> +    Print(L"      IN_USE                    - 0x%lx\n", CurrentImageInfo-
> >AttributesSetting & IMAGE_ATTRIBUTE_IN_USE);
> +    Print(L"      UEFI_IMAGE                - 0x%lx\n", CurrentImageInfo-
> >AttributesSetting & IMAGE_ATTRIBUTE_UEFI_IMAGE);
> +    Print(L"    Compatibilities             - 0x%lx\n", CurrentImageInfo-
> >Compatibilities);
> +    Print(L"      COMPATIB_CHECK_SUPPORTED  - 0x%lx\n", CurrentImageInfo-
> >Compatibilities & IMAGE_COMPATIBILITY_CHECK_SUPPORTED);
> +    if (DescriptorVersion > 1) {
> +      Print(L"    LowestSupportedImageVersion - 0x%x\n", CurrentImageInfo-
> >LowestSupportedImageVersion);
> +      if (DescriptorVersion > 2) {
> +        Print(L"    LastAttemptVersion          - 0x%x\n", CurrentImageInfo-
> >LastAttemptVersion);
> +        Print(L"    LastAttemptStatus           - 0x%x (%a)\n", CurrentImageInfo-
> >LastAttemptStatus, LastAttemptStatusToString(CurrentImageInfo->LastAttemptStatus));
> +        Print(L"    HardwareInstance            - 0x%lx\n", CurrentImageInfo-
> >HardwareInstance);
> +      }
> +    }
> +    //
> +    // Use DescriptorSize to move ImageInfo Pointer to stay compatible with different
> ImageInfo version
> +    //
> +    CurrentImageInfo = (EFI_FIRMWARE_IMAGE_DESCRIPTOR *)((UINT8 *)CurrentImageInfo +
> DescriptorSize);
> +  }
> +}
> +
> +/**
> +  Dump FMP package information.
> +
> +  @param PackageVersion             The version of package.
> +  @param PackageVersionName         The version name of package.
> +  @param PackageVersionNameMaxLen   The maximum length of PackageVersionName.
> +  @param AttributesSupported        Package attributes that are supported by this
> device.
> +  @param AttributesSetting          Package attributes.
> +**/
> +VOID
> +DumpFmpPackageInfo(
> +  IN UINT32                           PackageVersion,
> +  IN CHAR16                           *PackageVersionName,
> +  IN UINT32                           PackageVersionNameMaxLen,
> +  IN UINT64                           AttributesSupported,
> +  IN UINT64                           AttributesSetting
> +  )
> +{
> +  Print(L"  PackageVersion              - 0x%x\n", PackageVersion);
> +  Print(L"  PackageVersionName          - \"%s\"\n", PackageVersionName);
> +  Print(L"  PackageVersionNameMaxLen    - 0x%x\n", PackageVersionNameMaxLen);
> +  Print(L"  AttributesSupported         - 0x%lx\n", AttributesSupported);
> +  Print(L"    IMAGE_UPDATABLE           - 0x%lx\n", AttributesSupported &
> IMAGE_ATTRIBUTE_IMAGE_UPDATABLE);
> +  Print(L"    RESET_REQUIRED            - 0x%lx\n", AttributesSupported &
> IMAGE_ATTRIBUTE_RESET_REQUIRED);
> +  Print(L"    AUTHENTICATION_REQUIRED   - 0x%lx\n", AttributesSupported &
> IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);
> +  Print(L"  AttributesSetting           - 0x%lx\n", AttributesSetting);
> +  Print(L"    IMAGE_UPDATABLE           - 0x%lx\n", AttributesSetting &
> IMAGE_ATTRIBUTE_IMAGE_UPDATABLE);
> +  Print(L"    RESET_REQUIRED            - 0x%lx\n", AttributesSetting &
> IMAGE_ATTRIBUTE_RESET_REQUIRED);
> +  Print(L"    AUTHENTICATION_REQUIRED   - 0x%lx\n", AttributesSetting &
> IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);
> +}
> +
> +/**
> +  Dump FMP protocol info.
> +**/
> +VOID
> +DumpFmpData (
> +  VOID
> +  )
> +{
> +  EFI_STATUS                                    Status;
> +  EFI_FIRMWARE_MANAGEMENT_PROTOCOL              *Fmp;
> +  EFI_HANDLE                                    *HandleBuffer;
> +  UINTN                                         NumberOfHandles;
> +  UINTN                                         Index;
> +  EFI_FIRMWARE_IMAGE_DESCRIPTOR                 *FmpImageInfoBuf;
> +  UINTN                                         ImageInfoSize;
> +  UINT32                                        FmpImageInfoDescriptorVer;
> +  UINT8                                         FmpImageInfoCount;
> +  UINTN                                         DescriptorSize;
> +  UINT32                                        PackageVersion;
> +  CHAR16                                        *PackageVersionName;
> +  UINT32                                        PackageVersionNameMaxLen;
> +  UINT64                                        AttributesSupported;
> +  UINT64                                        AttributesSetting;
> +
> +  Print(L"############\n");
> +  Print(L"# FMP DATA #\n");
> +  Print(L"############\n");
> +  Status = gBS->LocateHandleBuffer (
> +                  ByProtocol,
> +                  &gEfiFirmwareManagementProtocolGuid,
> +                  NULL,
> +                  &NumberOfHandles,
> +                  &HandleBuffer
> +                  );
> +  if (EFI_ERROR(Status)) {
> +    Print(L"FMP protocol - %r\n", EFI_NOT_FOUND);
> +    return;
> +  }
> +
> +  for (Index = 0; Index < NumberOfHandles; Index++) {
> +    Status = gBS->HandleProtocol(
> +                    HandleBuffer[Index],
> +                    &gEfiFirmwareManagementProtocolGuid,
> +                    (VOID **)&Fmp
> +                    );
> +    if (EFI_ERROR(Status)) {
> +      continue;
> +    }
> +
> +    ImageInfoSize = 0;
> +    Status = Fmp->GetImageInfo (
> +                    Fmp,
> +                    &ImageInfoSize,
> +                    NULL,
> +                    NULL,
> +                    NULL,
> +                    NULL,
> +                    NULL,
> +                    NULL
> +                    );
> +    if (Status != EFI_BUFFER_TOO_SMALL) {
> +      continue;
> +    }
> +
> +    FmpImageInfoBuf = NULL;
> +    FmpImageInfoBuf = AllocateZeroPool (ImageInfoSize);
> +    if (FmpImageInfoBuf == NULL) {
> +      Status = EFI_OUT_OF_RESOURCES;
> +      goto EXIT;
> +    }
> +
> +    PackageVersionName = NULL;
> +    Status = Fmp->GetImageInfo (
> +                    Fmp,
> +                    &ImageInfoSize,               // ImageInfoSize
> +                    FmpImageInfoBuf,              // ImageInfo
> +                    &FmpImageInfoDescriptorVer,   // DescriptorVersion
> +                    &FmpImageInfoCount,           // DescriptorCount
> +                    &DescriptorSize,              // DescriptorSize
> +                    &PackageVersion,              // PackageVersion
> +                    &PackageVersionName           // PackageVersionName
> +                    );
> +
> +    //
> +    // If FMP GetInformation interface failed, skip this resource
> +    //
> +    if (EFI_ERROR(Status)) {
> +      Print(L"FMP (%d) ImageInfo - %r\n", Index, Status);
> +      FreePool(FmpImageInfoBuf);
> +      continue;
> +    }
> +
> +    Print(L"FMP (%d) ImageInfo:\n", Index);
> +    DumpFmpImageInfo(
> +      ImageInfoSize,               // ImageInfoSize
> +      FmpImageInfoBuf,             // ImageInfo
> +      FmpImageInfoDescriptorVer,   // DescriptorVersion
> +      FmpImageInfoCount,           // DescriptorCount
> +      DescriptorSize,              // DescriptorSize
> +      PackageVersion,              // PackageVersion
> +      PackageVersionName           // PackageVersionName
> +      );
> +
> +    if (PackageVersionName != NULL) {
> +      FreePool(PackageVersionName);
> +    }
> +    FreePool(FmpImageInfoBuf);
> +
> +    //
> +    // Get package info
> +    //
> +    PackageVersionName = NULL;
> +    Status = Fmp->GetPackageInfo (
> +                    Fmp,
> +                    &PackageVersion,              // PackageVersion
> +                    &PackageVersionName,          // PackageVersionName
> +                    &PackageVersionNameMaxLen,    // PackageVersionNameMaxLen
> +                    &AttributesSupported,         // AttributesSupported
> +                    &AttributesSetting            // AttributesSetting
> +                    );
> +    if (EFI_ERROR(Status)) {
> +      Print(L"FMP (%d) PackageInfo - %r\n", Index, Status);
> +    } else {
> +      Print(L"FMP (%d) ImageInfo:\n", Index);
> +      DumpFmpPackageInfo(
> +        PackageVersion,              // PackageVersion
> +        PackageVersionName,          // PackageVersionName
> +        PackageVersionNameMaxLen,    // PackageVersionNameMaxLen
> +        AttributesSupported,         // AttributesSupported
> +        AttributesSetting            // AttributesSetting
> +        );
> +
> +      if (PackageVersionName != NULL) {
> +        FreePool(PackageVersionName);
> +      }
> +    }
> +  }
> +  Print(L"\n");
> +
> +EXIT:
> +  FreePool(HandleBuffer);
> +}
> --
> 2.7.4.windows.1
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>
https://lists.01.org/mailman/listinfo/edk2-devel


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

* Re: [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application.
  2016-09-30  4:13           ` Ni, Ruiyu
@ 2016-09-30 15:30             ` Carsey, Jaben
  2016-10-03 18:35               ` Rothman, Michael A
  0 siblings, 1 reply; 83+ messages in thread
From: Carsey, Jaben @ 2016-09-30 15:30 UTC (permalink / raw)
  To: Ni, Ruiyu, Yao, Jiewen, Kinney, Michael D,
	edk2-devel@lists.01.org, Rothman, Michael A
  Cc: Tian, Feng, Zhang, Chao B, Gao, Liming, Zeng, Star, Carsey, Jaben

Mike Rothman,

Can we get LoadOptions and LoadOptionsSize clarified in the UEFI Spec?  This seems like a simple clarification and I would argue its needed.  The UEFI Shell is not the only producer of this protocol.  BDS launches things (like the UEFI Shell itself) and the shell already consumes it for itself (and it works).  I think it just needs clarification so people can depend on the current implementation not changing.

-Jaben

From: Ni, Ruiyu
Sent: Thursday, September 29, 2016 9:13 PM
To: Carsey, Jaben <jaben.carsey@intel.com>; Yao, Jiewen <jiewen.yao@intel.com>; Kinney, Michael D <michael.d.kinney@intel.com>; edk2-devel@lists.01.org
Cc: Tian, Feng <feng.tian@intel.com>; Zhang, Chao B <chao.b.zhang@intel.com>; Gao, Liming <liming.gao@intel.com>; Zeng, Star <star.zeng@intel.com>
Subject: RE: [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application.
Importance: High

Supposing user inputs "CapsuleApp.efi Parameter1 Parameter2".
There is no spec to define what the LoadOption should equal to.
If there is another UEFI Shell implementation, it could interpret the command line then sets only "Parameter1 Parameter2" into LoadOption, or sets "CapsuleApp.efi\tParameter1\tParameter2" to LoadOption, or sets "[Shell]\tCapsuleApp.efi\tParameter1\tParameter2" to LoadOption.
Because it"produces" such LoadOption, it knows how to "consume"/parse it to get the ARGVs.

So I suggest we put the CapsuleApp in ShellPkg and let it use the ShellParameter protocol.

Regards,
Ray

From: Carsey, Jaben
Sent: Friday, September 30, 2016 3:11 AM
To: Ni, Ruiyu <ruiyu.ni@intel.com<mailto:ruiyu.ni@intel.com>>; Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>; edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>
Cc: Tian, Feng <feng.tian@intel.com<mailto:feng.tian@intel.com>>; Zhang, Chao B <chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com>>; Gao, Liming <liming.gao@intel.com<mailto:liming.gao@intel.com>>; Zeng, Star <star.zeng@intel.com<mailto:star.zeng@intel.com>>; Carsey, Jaben <jaben.carsey@intel.com<mailto:jaben.carsey@intel.com>>
Subject: RE: [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application.

I am confused.

Why is LoadOption and LoadOptionSize not working?  This is specified as part of UEFI Spec (Note: Not UEFI Shell Spec) as a standard way to pass parameters to UEFI appliations.  I think this should work (although it is more work than just examining argc/argv).

-Jaben

From: Ni, Ruiyu
Sent: Wednesday, September 28, 2016 11:40 PM
To: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>; edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>
Cc: Tian, Feng <feng.tian@intel.com<mailto:feng.tian@intel.com>>; Zhang, Chao B <chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com>>; Gao, Liming <liming.gao@intel.com<mailto:liming.gao@intel.com>>; Zeng, Star <star.zeng@intel.com<mailto:star.zeng@intel.com>>; Carsey, Jaben <jaben.carsey@intel.com<mailto:jaben.carsey@intel.com>>
Subject: RE: [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application.
Importance: High

Jiewen,
The way CapsuleApp extracts the ARGV assumes UEFI Shell encodes the parameters using a certain way. But the parameter encoding way is not described in the Shell spec.
Maybe we can put the CapsuleApp in ShellPkg, then let it directly use ShellParameter protocol to get the ARGV.

Copying Jaben.

Regards,
Ray

From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of Yao, Jiewen
Sent: Thursday, September 29, 2016 10:37 AM
To: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>; edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>
Cc: Tian, Feng <feng.tian@intel.com<mailto:feng.tian@intel.com>>; Zhang, Chao B <chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com>>; Gao, Liming <liming.gao@intel.com<mailto:liming.gao@intel.com>>; Zeng, Star <star.zeng@intel.com<mailto:star.zeng@intel.com>>
Subject: Re: [edk2] [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application.

Right. CapsuleOnDisk is not supported in BIOS yet.
I will remove it in CapsuleApp.

CapsuleApp just works as an agent to pass capsule to CapsuleDxeRuntime driver.
So it is checked by CapsuleDxeRuntime, not CapsuleApp.

Thank you
Yao Jiewen

From: Kinney, Michael D
Sent: Thursday, September 29, 2016 9:06 AM
To: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>; Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>
Cc: Tian, Feng <feng.tian@intel.com<mailto:feng.tian@intel.com>>; Zeng, Star <star.zeng@intel.com<mailto:star.zeng@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: [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application.

Jiewen,

Does the capsule on disk feature provided by this app work?

I tried it with the QuarkPlatformPkg capsule and I can get
The app to copy the capsule to an EFI System Partition, but
The logic after that point looks incomplete.

Also, if I clear the Persist and Reset flags on the capsule,
the immediate processing of the capsule does not work.

Is there any FW code that will look for capsules on disk?

If there are incomplete features in CapsuleApp, then I think
we should remove them.

Mike

> -----Original Message-----
> From: Yao, Jiewen
> Sent: Tuesday, September 20, 2016 11:45 PM
> To: edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org%3cmailto:edk2-devel@lists.01.org>>
> Cc: Tian, Feng <feng.tian@intel.com<mailto:feng.tian@intel.com<mailto:feng.tian@intel.com%3cmailto:feng.tian@intel.com>>>; Zeng, Star <star.zeng@intel.com<mailto:star.zeng@intel.com<mailto:star.zeng@intel.com%3cmailto:star.zeng@intel.com>>>; Kinney, Michael
> D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com%3cmailto:michael.d.kinney@intel.com>>>; Gao, Liming <liming.gao@intel.com<mailto:liming.gao@intel.com<mailto:liming.gao@intel.com%3cmailto:liming.gao@intel.com>>>; Zhang, Chao B
> <chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com%3cmailto:chao.b.zhang@intel.com>>>
> Subject: [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application.
>
> This CapsuleApp can help perform capsule update in UEFI shell environment.
> It can also dump capsule information, capsule status variable, ESRT and FMP.
>
> Cc: Feng Tian <feng.tian@intel.com<mailto:feng.tian@intel.com<mailto:feng.tian@intel.com%3cmailto:feng.tian@intel.com>>>
> Cc: Star Zeng <star.zeng@intel.com<mailto:star.zeng@intel.com<mailto:star.zeng@intel.com%3cmailto:star.zeng@intel.com>>>
> Cc: Michael D Kinney <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com%3cmailto:michael.d.kinney@intel.com>>>
> Cc: Liming Gao <liming.gao@intel.com<mailto:liming.gao@intel.com<mailto:liming.gao@intel.com%3cmailto:liming.gao@intel.com>>>
> Cc: Chao Zhang <chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com%3cmailto:chao.b.zhang@intel.com>>>
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Jiewen Yao <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com<mailto:jiewen.yao@intel.com%3cmailto:jiewen.yao@intel.com>>>
> ---
>  MdeModulePkg/Application/CapsuleApp/AppSupport.c        |  480 +++++++++
>  MdeModulePkg/Application/CapsuleApp/CapsuleApp.c        | 1047 ++++++++++++++++++++
>  MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf      |   71 ++
>  MdeModulePkg/Application/CapsuleApp/CapsuleApp.uni      |   22 +
>  MdeModulePkg/Application/CapsuleApp/CapsuleAppExtra.uni |   19 +
>  MdeModulePkg/Application/CapsuleApp/CapsuleDump.c       |  840 ++++++++++++++++
>  6 files changed, 2479 insertions(+)
>
> diff --git a/MdeModulePkg/Application/CapsuleApp/AppSupport.c
> b/MdeModulePkg/Application/CapsuleApp/AppSupport.c
> new file mode 100644
> index 0000000..365067d
> --- /dev/null
> +++ b/MdeModulePkg/Application/CapsuleApp/AppSupport.c
> @@ -0,0 +1,480 @@
> +/** @file
> +  A shell application that triggers capsule update process.
> +
> +  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the BSD License
> +  which accompanies this distribution.  The full text of the license may be found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +
> +**/
> +
> +#include <Uefi.h>
> +#include <Library/BaseLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/UefiRuntimeServicesTableLib.h>
> +#include <Library/UefiLib.h>
> +#include <Library/PrintLib.h>
> +#include <Protocol/LoadedImage.h>
> +#include <Protocol/SimpleFileSystem.h>
> +#include <Guid/FileInfo.h>
> +#include <Guid/Gpt.h>
> +
> +#define MAX_ARG_NUM     11
> +
> +UINTN  Argc = 0;
> +CHAR16 *Argv[MAX_ARG_NUM];
> +CHAR16 *ArgBuffer;
> +
> +/**
> +
> +  This function parse application ARG.
> +
> +  @return Status
> +**/
> +EFI_STATUS
> +GetArg (
> +  VOID
> +  )
> +{
> +  UINT8                         *Data;
> +  UINTN                         DataSize;
> +  CHAR16                        *Index;
> +  CHAR16                        *End;
> +  CHAR16                        *DIndex;
> +  EFI_STATUS                    Status;
> +  EFI_LOADED_IMAGE_PROTOCOL     *LoadedImage;
> +
> +  Status = gBS->HandleProtocol (
> +                  gImageHandle,
> +                  &gEfiLoadedImageProtocolGuid,
> +                  (VOID**)&LoadedImage
> +                  );
> +  if (EFI_ERROR(Status)) {
> +    return Status;
> +  }
> +
> +  Data = LoadedImage->LoadOptions;
> +  DataSize = LoadedImage->LoadOptionsSize;
> +
> +  End = (CHAR16*)(UINTN)(Data + DataSize);
> +  Status = gBS->AllocatePool (EfiBootServicesData, DataSize, (VOID **)&ArgBuffer);
> +  ASSERT_EFI_ERROR (Status);
> +  DIndex = ArgBuffer;
> +  Argv[Argc++] = ArgBuffer;
> +  for (Index = (CHAR16*)Data; Index < End; ) {
> +    if (*Index == L' ') {
> +      *DIndex = L'\0';
> +      if (Argc >= MAX_ARG_NUM) {
> +        return EFI_UNSUPPORTED;
> +      }
> +      Argv[Argc++] = (++ DIndex);
> +      while(*Index == L' ') {
> +        Index ++;
> +      }
> +    }
> +    (*(DIndex ++)) = (*(Index ++));
> +  }
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Clear APP ARG.
> +**/
> +VOID
> +CleanArg (
> +  VOID
> +  )
> +{
> +  FreePool (Argv[0]);
> +}
> +
> +/**
> +  Return File System Volume containing this shell application.
> +
> +  @return File System Volume containing this shell application.
> +**/
> +EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *
> +GetMyVol (
> +  VOID
> +  )
> +{
> +  EFI_STATUS                        Status;
> +  EFI_LOADED_IMAGE_PROTOCOL         *LoadedImage;
> +  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Vol;
> +
> +  Status = gBS->HandleProtocol (
> +                  gImageHandle,
> +                  &gEfiLoadedImageProtocolGuid,
> +                  (VOID **)&LoadedImage
> +                  );
> +  ASSERT_EFI_ERROR (Status);
> +
> +  Status = gBS->HandleProtocol (
> +                  LoadedImage->DeviceHandle,
> +                  &gEfiSimpleFileSystemProtocolGuid,
> +                  (VOID **)&Vol
> +                  );
> +  if (!EFI_ERROR (Status)) {
> +    return Vol;
> +  }
> +
> +  return NULL;
> +}
> +
> +/**
> +  Read a file from this volume.
> +
> +  @param Vol             File System Volume
> +  @param FileName        The file to be read.
> +  @param BufferSize      The file buffer size
> +  @param Buffer          The file buffer
> +
> +  @retval EFI_SUCCESS    Read file successfully
> +  @retval EFI_NOT_FOUND  File not found
> +**/
> +EFI_STATUS
> +ReadFileFromVol (
> +  IN  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Vol,
> +  IN  CHAR16                            *FileName,
> +  OUT UINTN                             *BufferSize,
> +  OUT VOID                              **Buffer
> +  )
> +{
> +  EFI_STATUS                        Status;
> +  EFI_FILE_HANDLE                   RootDir;
> +  EFI_FILE_HANDLE                   Handle;
> +  UINTN                             FileInfoSize;
> +  EFI_FILE_INFO                     *FileInfo;
> +  UINTN                             TempBufferSize;
> +  VOID                              *TempBuffer;
> +
> +  //
> +  // Open the root directory
> +  //
> +  Status = Vol->OpenVolume (Vol, &RootDir);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  //
> +  // Open the file
> +  //
> +  Status = RootDir->Open (
> +                      RootDir,
> +                      &Handle,
> +                      FileName,
> +                      EFI_FILE_MODE_READ,
> +                      0
> +                      );
> +  if (EFI_ERROR (Status)) {
> +    RootDir->Close (RootDir);
> +    return Status;
> +  }
> +
> +  RootDir->Close (RootDir);
> +
> +  //
> +  // Get the file information
> +  //
> +  FileInfoSize = sizeof(EFI_FILE_INFO) + 1024;
> +
> +  FileInfo = AllocateZeroPool (FileInfoSize);
> +  if (FileInfo == NULL) {
> +    Handle->Close (Handle);
> +    return Status;
> +  }
> +
> +  Status = Handle->GetInfo (
> +                     Handle,
> +                     &gEfiFileInfoGuid,
> +                     &FileInfoSize,
> +                     FileInfo
> +                     );
> +  if (EFI_ERROR (Status)) {
> +    Handle->Close (Handle);
> +    gBS->FreePool (FileInfo);
> +    return Status;
> +  }
> +
> +  //
> +  // Allocate buffer for the file data. The last CHAR16 is for L'\0'
> +  //
> +  TempBufferSize = (UINTN) FileInfo->FileSize + sizeof(CHAR16);
> +  TempBuffer = AllocateZeroPool (TempBufferSize);
> +  if (TempBuffer == NULL) {
> +    Handle->Close (Handle);
> +    gBS->FreePool (FileInfo);
> +    return Status;
> +  }
> +
> +  gBS->FreePool (FileInfo);
> +
> +  //
> +  // Read the file data to the buffer
> +  //
> +  Status = Handle->Read (
> +                     Handle,
> +                     &TempBufferSize,
> +                     TempBuffer
> +                     );
> +  if (EFI_ERROR (Status)) {
> +    Handle->Close (Handle);
> +    gBS->FreePool (TempBuffer);
> +    return Status;
> +  }
> +
> +  Handle->Close (Handle);
> +
> +  *BufferSize = TempBufferSize;
> +  *Buffer     = TempBuffer;
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Read a file.
> +  If ScanFs is FLASE, it will use this Vol as default Fs.
> +  If ScanFs is TRUE, it will scan all FS and check the file.
> +    If there is only one file match the name, it will be read.
> +    If there is more than one file match the name, it will return Error.
> +
> +  @param ThisVol         File System Volume
> +  @param FileName        The file to be read.
> +  @param BufferSize      The file buffer size
> +  @param Buffer          The file buffer
> +  @param ScanFs          Need Scan all FS
> +
> +  @retval EFI_SUCCESS    Read file successfully
> +  @retval EFI_NOT_FOUND  File not found
> +  @retval EFI_NO_MAPPING There is duplicated files found
> +**/
> +EFI_STATUS
> +ReadFileToBufferEx (
> +  IN OUT EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   **ThisVol,
> +  IN  CHAR16                               *FileName,
> +  OUT UINTN                                *BufferSize,
> +  OUT VOID                                 **Buffer,
> +  IN  BOOLEAN                              ScanFs
> +  )
> +{
> +  EFI_STATUS                        Status;
> +  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Vol;
> +  UINTN                             TempBufferSize;
> +  VOID                              *TempBuffer;
> +  UINTN                             NoHandles;
> +  EFI_HANDLE                        *HandleBuffer;
> +  UINTN                             Index;
> +
> +  //
> +  // Check parameters
> +  //
> +  if ((FileName == NULL) || (Buffer == NULL) || (ThisVol == NULL)) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  //
> +  // not scan fs
> +  //
> +  if (!ScanFs) {
> +    if (*ThisVol == NULL) {
> +      *ThisVol = GetMyVol ();
> +      if (*ThisVol == NULL) {
> +        return EFI_INVALID_PARAMETER;
> +      }
> +    }
> +    //
> +    // Read file directly from Vol
> +    //
> +    return ReadFileFromVol (*ThisVol, FileName, BufferSize, Buffer);
> +  }
> +
> +  //
> +  // need scan fs
> +  //
> +
> +  //
> +  // Get all Vol handle
> +  //
> +  Status = gBS->LocateHandleBuffer (
> +                   ByProtocol,
> +                   &gEfiSimpleFileSystemProtocolGuid,
> +                   NULL,
> +                   &NoHandles,
> +                   &HandleBuffer
> +                   );
> +  if (EFI_ERROR (Status) && (NoHandles == 0)) {
> +    return EFI_NOT_FOUND;
> +  }
> +
> +  //
> +  // Walk through each Vol
> +  //
> +  *ThisVol = NULL;
> +  *BufferSize = 0;
> +  *Buffer     = NULL;
> +  for (Index = 0; Index < NoHandles; Index++) {
> +    Status = gBS->HandleProtocol (
> +                    HandleBuffer[Index],
> +                    &gEfiSimpleFileSystemProtocolGuid,
> +                    (VOID **)&Vol
> +                    );
> +    if (EFI_ERROR(Status)) {
> +      continue;
> +    }
> +
> +    Status = ReadFileFromVol (Vol, FileName, &TempBufferSize, &TempBuffer);
> +    if (!EFI_ERROR (Status)) {
> +      //
> +      // Read file OK, check duplication
> +      //
> +      if (*ThisVol != NULL) {
> +        //
> +        // Find the duplicated file
> +        //
> +        gBS->FreePool (TempBuffer);
> +        gBS->FreePool (*Buffer);
> +        Print (L"Duplicated FileName found!\n");
> +        return EFI_NO_MAPPING;
> +      } else {
> +        //
> +        // Record value
> +        //
> +        *ThisVol = Vol;
> +        *BufferSize = TempBufferSize;
> +        *Buffer     = TempBuffer;
> +      }
> +    }
> +  }
> +
> +  //
> +  // Scan Fs done
> +  //
> +  if (*ThisVol == NULL) {
> +    return EFI_NOT_FOUND;
> +  }
> +
> +  //
> +  // Done
> +  //
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Read a file.
> +
> +  @param FileName        The file to be read.
> +  @param BufferSize      The file buffer size
> +  @param Buffer          The file buffer
> +
> +  @retval EFI_SUCCESS    Read file successfully
> +  @retval EFI_NOT_FOUND  File not found
> +**/
> +EFI_STATUS
> +ReadFileToBuffer (
> +  IN  CHAR16                               *FileName,
> +  OUT UINTN                                *BufferSize,
> +  OUT VOID                                 **Buffer
> +  )
> +{
> +  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Vol;
> +  Vol = NULL;
> +  return ReadFileToBufferEx(&Vol, FileName, BufferSize, Buffer, FALSE);
> +}
> +
> +/**
> +  Write a file.
> +
> +  @param FileName        The file to be written.
> +  @param BufferSize      The file buffer size
> +  @param Buffer          The file buffer
> +
> +  @retval EFI_SUCCESS    Write file successfully
> +**/
> +EFI_STATUS
> +WriteFileFromBuffer(
> +  IN  CHAR16                               *FileName,
> +  IN  UINTN                                BufferSize,
> +  IN  VOID                                 *Buffer
> +  )
> +{
> +  EFI_STATUS                        Status;
> +  EFI_FILE_HANDLE                   RootDir;
> +  EFI_FILE_HANDLE                   Handle;
> +  UINTN                             TempBufferSize;
> +  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Vol;
> +
> +  Vol = GetMyVol();
> +
> +  //
> +  // Open the root directory
> +  //
> +  Status = Vol->OpenVolume (Vol, &RootDir);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  //
> +  // Open the file
> +  //
> +  Status = RootDir->Open (
> +                      RootDir,
> +                      &Handle,
> +                      FileName,
> +                      EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE| EFI_FILE_MODE_CREATE,
> +                      0
> +                      );
> +  if (EFI_ERROR (Status)) {
> +    RootDir->Close (RootDir);
> +    return Status;
> +  }
> +
> +  //
> +  // Delete file
> +  //
> +  Status = Handle->Delete(Handle);
> +  if (EFI_ERROR(Status)) {
> +    return Status;
> +  }
> +
> +  //
> +  // Open the file again
> +  //
> +  Status = RootDir->Open (
> +                      RootDir,
> +                      &Handle,
> +                      FileName,
> +                      EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE| EFI_FILE_MODE_CREATE,
> +                      0
> +                      );
> +  if (EFI_ERROR (Status)) {
> +    RootDir->Close (RootDir);
> +    return Status;
> +  }
> +
> +  RootDir->Close (RootDir);
> +
> +  //
> +  // Write the file data from the buffer
> +  //
> +  TempBufferSize = BufferSize;
> +  Status = Handle->Write (
> +                     Handle,
> +                     &TempBufferSize,
> +                     Buffer
> +                     );
> +  if (EFI_ERROR (Status)) {
> +    Handle->Close (Handle);
> +    return Status;
> +  }
> +
> +  Handle->Close (Handle);
> +
> +  return EFI_SUCCESS;
> +}
> +
> diff --git a/MdeModulePkg/Application/CapsuleApp/CapsuleApp.c
> b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.c
> new file mode 100644
> index 0000000..0a28557
> --- /dev/null
> +++ b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.c
> @@ -0,0 +1,1047 @@
> +/** @file
> +  A shell application that triggers capsule update process.
> +
> +  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the BSD License
> +  which accompanies this distribution.  The full text of the license may be found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +
> +**/
> +
> +#include <Uefi.h>
> +#include <Library/BaseLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/UefiRuntimeServicesTableLib.h>
> +#include <Library/UefiLib.h>
> +#include <Library/PrintLib.h>
> +#include <Protocol/LoadedImage.h>
> +#include <Protocol/SimpleFileSystem.h>
> +#include <Protocol/GraphicsOutput.h>
> +#include <Guid/FileInfo.h>
> +#include <Guid/Gpt.h>
> +#include <Guid/GlobalVariable.h>
> +#include <Guid/CapsuleReport.h>
> +#include <Guid/SystemResourceTable.h>
> +#include <Guid/FmpCapsule.h>
> +#include <IndustryStandard/WindowsUxCapsule.h>
> +
> +#define CAPSULE_HEADER_SIZE  0x20
> +
> +#define NESTED_CAPSULE_HEADER_SIZE  SIZE_4KB
> +#define SYSTEM_FIRMWARE_FLAG 0x50000
> +#define DEVICE_FIRMWARE_FLAG 0x78010
> +
> +#define EFI_CAPSULE_FROM_FILE_DIR                           L"\\EFI\\UpdateCapsule\\<file:///\\EFI\UpdateCapsule\><file:///\\EFI\UpdateCapsule\%3cfile:\EFI\UpdateCapsule\%3e>"
> +#define EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED  0x0000000000000004
> +
> +#define MAJOR_VERSION   1
> +#define MINOR_VERSION   0
> +
> +#define MAX_ARG_NUM     11
> +#define MAX_CAPSULE_NUM (MAX_ARG_NUM - 1)
> +
> +extern UINTN  Argc;
> +extern CHAR16 *Argv[];
> +
> +//
> +// Define how many block descriptors we want to test with.
> +//
> +UINTN  NumberOfDescriptors = 1;
> +UINTN  CapsuleFirstIndex;
> +UINTN  CapsuleLastIndex;
> +
> +/**
> +  Dump capsule information
> +
> +  @retval EFI_SUCCESS            The capsule information is dumped.
> +  @retval EFI_UNSUPPORTED        Input parameter is not valid.
> +**/
> +EFI_STATUS
> +DumpCapsule(
> +  VOID
> +  );
> +
> +/**
> +  Dump capsule status variable.
> +
> +  @retval EFI_SUCCESS            The capsule status variable is dumped.
> +  @retval EFI_UNSUPPORTED        Input parameter is not valid.
> +**/
> +EFI_STATUS
> +DmpCapsuleStatusVariable(
> +  VOID
> +  );
> +
> +/**
> +  Dump FMP protocol info.
> +**/
> +VOID
> +DumpFmpData(
> +  VOID
> +  );
> +
> +/**
> +  Dump ESRT info.
> +**/
> +VOID
> +DumpEsrtData(
> +  VOID
> +  );
> +
> +/**
> +  Read a file.
> +
> +  @param FileName        The file to be read.
> +  @param BufferSize      The file buffer size
> +  @param Buffer          The file buffer
> +
> +  @retval EFI_SUCCESS    Read file successfully
> +  @retval EFI_NOT_FOUND  File not found
> +**/
> +EFI_STATUS
> +ReadFileToBuffer(
> +  IN  CHAR16                               *FileName,
> +  OUT UINTN                                *BufferSize,
> +  OUT VOID                                 **Buffer
> +  );
> +
> +/**
> +  Write a file.
> +
> +  @param FileName        The file to be written.
> +  @param BufferSize      The file buffer size
> +  @param Buffer          The file buffer
> +
> +  @retval EFI_SUCCESS    Write file successfully
> +**/
> +EFI_STATUS
> +WriteFileFromBuffer(
> +  IN  CHAR16                               *FileName,
> +  IN  UINTN                                BufferSize,
> +  IN  VOID                                 *Buffer
> +  );
> +
> +/**
> +
> +  This function parse application ARG.
> +
> +  @return Status
> +**/
> +EFI_STATUS
> +GetArg (
> +  VOID
> +  );
> +
> +/**
> +  Clear APP ARG.
> +**/
> +VOID
> +CleanArg (
> +  VOID
> +  );
> +
> +/**
> +  Create UX capsule.
> +
> +  @retval EFI_SUCCESS            The capsule header is appended.
> +  @retval EFI_UNSUPPORTED        Input parameter is not valid.
> +  @retval EFI_OUT_OF_RESOURCES   No enough resource to create UX capsule.
> +**/
> +EFI_STATUS
> +CreateBmpFmp(
> +  VOID
> +  )
> +{
> +  CHAR16                                        *OutputCapsuleName;
> +  VOID                                          *BmpBuffer;
> +  UINTN                                         FileSize;
> +  CHAR16                                        *BmpName;
> +  UINT8                                         *FullCapsuleBuffer;
> +  UINTN                                         FullCapsuleBufferSize;
> +  EFI_DISPLAY_CAPSULE                           *DisplayCapsule;
> +  EFI_STATUS                                    Status;
> +  EFI_GRAPHICS_OUTPUT_PROTOCOL                  *Gop;
> +
> +  Status = gBS->LocateProtocol(&gEfiGraphicsOutputProtocolGuid, NULL, (VOID **)&Gop);
> +  if (EFI_ERROR(Status)) {
> +    Print(L"CapsuleApp: NO GOP is found.\n");
> +    return EFI_UNSUPPORTED;
> +  }
> +  Print(L"Current GOP: Mode - %d, ", Gop->Mode->Mode);
> +  Print(L"HorizontalResolution - %d, ", Gop->Mode->Info->HorizontalResolution);
> +  Print(L"VerticalResolution - %d\n", Gop->Mode->Info->VerticalResolution);
> +  // HorizontalResolution >= BMP_IMAGE_HEADER.PixelWidth
> +  // VerticalResolution   >= BMP_IMAGE_HEADER.PixelHeight
> +
> +  if (Argc != 5) {
> +    Print(L"CapsuleApp: Invalid Parameter.\n");
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  if (StrCmp(Argv[3], L"-O") != 0) {
> +    Print(L"CapsuleApp: NO output capsule name.\n");
> +    return EFI_UNSUPPORTED;
> +  }
> +  OutputCapsuleName = Argv[4];
> +
> +  BmpBuffer = NULL;
> +  FileSize = 0;
> +  FullCapsuleBuffer = NULL;
> +
> +  BmpName = Argv[2];
> +  Status = ReadFileToBuffer(BmpName, &FileSize, &BmpBuffer);
> +  if (EFI_ERROR(Status)) {
> +    Print(L"CapsuleApp: BMP image (%s) is not found.\n", BmpName);
> +    goto Done;
> +  }
> +
> +  FullCapsuleBufferSize = sizeof(EFI_DISPLAY_CAPSULE) + FileSize;
> +  FullCapsuleBuffer = AllocatePool(FullCapsuleBufferSize);
> +  if (FullCapsuleBuffer == NULL) {
> +    Print(L"CapsuleApp: Capsule Buffer size (0x%x) too big.\n",
> FullCapsuleBufferSize);
> +    Status = EFI_OUT_OF_RESOURCES;
> +    goto Done;
> +  }
> +
> +  DisplayCapsule = (EFI_DISPLAY_CAPSULE *)FullCapsuleBuffer;
> +  CopyGuid(&DisplayCapsule->CapsuleHeader.CapsuleGuid, &gWindowsUxCapsuleGuid);
> +  DisplayCapsule->CapsuleHeader.HeaderSize = sizeof(DisplayCapsule->CapsuleHeader);
> +  DisplayCapsule->CapsuleHeader.Flags = CAPSULE_FLAGS_PERSIST_ACROSS_RESET;
> +  DisplayCapsule->CapsuleHeader.CapsuleImageSize = (UINT32)FullCapsuleBufferSize;
> +
> +  DisplayCapsule->ImagePayload.Version = 1;
> +  DisplayCapsule->ImagePayload.Checksum = 0;
> +  DisplayCapsule->ImagePayload.ImageType = 0; // BMP
> +  DisplayCapsule->ImagePayload.Reserved = 0;
> +  DisplayCapsule->ImagePayload.Mode = Gop->Mode->Mode;
> +  DisplayCapsule->ImagePayload.OffsetX = 0;
> +  DisplayCapsule->ImagePayload.OffsetY = 0;
> +
> +  CopyMem((DisplayCapsule + 1), BmpBuffer, FileSize);
> +
> +  DisplayCapsule->ImagePayload.Checksum = CalculateCheckSum8(FullCapsuleBuffer,
> FullCapsuleBufferSize);
> +
> +  Status = WriteFileFromBuffer(OutputCapsuleName, FullCapsuleBufferSize,
> FullCapsuleBuffer);
> +  Print(L"CapsuleApp: Write %s %r\n", OutputCapsuleName, Status);
> +
> +Done:
> +  if (BmpBuffer != NULL) {
> +    FreePool(BmpBuffer);
> +  }
> +
> +  if (FullCapsuleBuffer != NULL) {
> +    FreePool(FullCapsuleBuffer);
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  Get ImageTypeId in the FMP capsule header.
> +
> +  @param CapsuleHeader  The FMP capsule image header.
> +
> +  @return ImageTypeId
> +**/
> +EFI_GUID *
> +GetCapsuleImageTypeId(
> +  IN EFI_CAPSULE_HEADER                            *CapsuleHeader
> +  )
> +{
> +  EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER       *FmpCapsuleHeader;
> +  UINT64                                       *ItemOffsetList;
> +  EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader;
> +
> +  FmpCapsuleHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *)((UINT8 *)CapsuleHeader
> + CapsuleHeader->HeaderSize);
> +  ItemOffsetList = (UINT64 *)(FmpCapsuleHeader + 1);
> +  if (FmpCapsuleHeader->PayloadItemCount == 0) {
> +    return NULL;
> +  }
> +  ImageHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *)((UINT8
> *)FmpCapsuleHeader + ItemOffsetList[FmpCapsuleHeader->EmbeddedDriverCount]);
> +  return &ImageHeader->UpdateImageTypeId;
> +}
> +
> +/**
> +  Get ESRT FwType according to ImageTypeId
> +
> +  @param  ImageTypeId   ImageTypeId of an FMP capsule.
> +
> +  @return ESRT FwType
> +**/
> +UINT32
> +GetEsrtFwType(
> +  IN  EFI_GUID                                      *ImageTypeId
> +  )
> +{
> +  EFI_STATUS                 Status;
> +  EFI_SYSTEM_RESOURCE_TABLE  *Esrt;
> +  EFI_SYSTEM_RESOURCE_ENTRY  *EsrtEntry;
> +  UINTN                      Index;
> +
> +  //
> +  // Check ESRT
> +  //
> +  Status = EfiGetSystemConfigurationTable(&gEfiSystemResourceTableGuid, (VOID
> **)&Esrt);
> +  if (!EFI_ERROR(Status)) {
> +    EsrtEntry = (VOID *)(Esrt + 1);
> +    for (Index = 0; Index < Esrt->FwResourceCount; Index++, EsrtEntry++) {
> +      if (CompareGuid(&EsrtEntry->FwClass, ImageTypeId)) {
> +        return EsrtEntry->FwType;
> +      }
> +    }
> +  }
> +
> +  return ESRT_FW_TYPE_UNKNOWN;
> +}
> +
> +/**
> +  Append a capsule header on top of current image.
> +  This function follows Windows UEFI Firmware Update Platform document.
> +
> +  @retval EFI_SUCCESS            The capsule header is appended.
> +  @retval EFI_UNSUPPORTED        Input parameter is not valid.
> +  @retval EFI_OUT_OF_RESOURCES   No enough resource to append capsule header.
> +**/
> +EFI_STATUS
> +CreateNestedFmp(
> +  VOID
> +  )
> +{
> +  CHAR16                                        *OutputCapsuleName;
> +  VOID                                          *CapsuleBuffer;
> +  UINTN                                         FileSize;
> +  CHAR16                                        *CapsuleName;
> +  UINT8                                         *FullCapsuleBuffer;
> +  UINTN                                         FullCapsuleBufferSize;
> +  EFI_CAPSULE_HEADER                            *NestedCapsuleHeader;
> +  EFI_GUID                                      *ImageTypeId;
> +  UINT32                                        FwType;
> +  EFI_STATUS                                    Status;
> +
> +  if (Argc != 5) {
> +    Print(L"CapsuleApp: Invalid Parameter.\n");
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  if (StrCmp(Argv[3], L"-O") != 0) {
> +    Print(L"CapsuleApp: NO output capsule name.\n");
> +    return EFI_UNSUPPORTED;
> +  }
> +  OutputCapsuleName = Argv[4];
> +
> +  CapsuleBuffer = NULL;
> +  FileSize = 0;
> +  FullCapsuleBuffer = NULL;
> +
> +  CapsuleName = Argv[2];
> +  Status = ReadFileToBuffer(CapsuleName, &FileSize, &CapsuleBuffer);
> +  if (EFI_ERROR(Status)) {
> +    Print(L"CapsuleApp: Capsule image (%s) is not found.\n", CapsuleName);
> +    goto Done;
> +  }
> +
> +  ImageTypeId = GetCapsuleImageTypeId(CapsuleBuffer);
> +  if (ImageTypeId == NULL) {
> +    Print(L"CapsuleApp: Capsule ImageTypeId is not found.\n");
> +    goto Done;
> +  }
> +  FwType = GetEsrtFwType(ImageTypeId);
> +  if ((FwType != ESRT_FW_TYPE_SYSTEMFIRMWARE) && (FwType !=
> ESRT_FW_TYPE_DEVICEFIRMWARE)) {
> +    Print(L"CapsuleApp: Capsule FwType is invalid.\n");
> +    goto Done;
> +  }
> +
> +  FullCapsuleBufferSize = NESTED_CAPSULE_HEADER_SIZE + FileSize;
> +  FullCapsuleBuffer = AllocatePool(FullCapsuleBufferSize);
> +  if (FullCapsuleBuffer == NULL) {
> +    Print(L"CapsuleApp: Capsule Buffer size (0x%x) too big.\n",
> FullCapsuleBufferSize);
> +    Status = EFI_OUT_OF_RESOURCES;
> +    goto Done;
> +  }
> +
> +  NestedCapsuleHeader = (EFI_CAPSULE_HEADER *)FullCapsuleBuffer;
> +  ZeroMem(NestedCapsuleHeader, NESTED_CAPSULE_HEADER_SIZE);
> +  CopyGuid(&NestedCapsuleHeader->CapsuleGuid, ImageTypeId);
> +  NestedCapsuleHeader->HeaderSize = NESTED_CAPSULE_HEADER_SIZE;
> +  NestedCapsuleHeader->Flags = (FwType == ESRT_FW_TYPE_DEVICEFIRMWARE) ?
> SYSTEM_FIRMWARE_FLAG : DEVICE_FIRMWARE_FLAG;
> +  NestedCapsuleHeader->CapsuleImageSize = (UINT32)FullCapsuleBufferSize;
> +
> +  CopyMem((UINT8 *)NestedCapsuleHeader + NestedCapsuleHeader->HeaderSize,
> CapsuleBuffer, FileSize);
> +
> +  Status = WriteFileFromBuffer(OutputCapsuleName, FullCapsuleBufferSize,
> FullCapsuleBuffer);
> +  Print(L"CapsuleApp: Write %s %r\n", OutputCapsuleName, Status);
> +
> +Done:
> +  if (CapsuleBuffer != NULL) {
> +    FreePool(CapsuleBuffer);
> +  }
> +
> +  if (FullCapsuleBuffer != NULL) {
> +    FreePool(FullCapsuleBuffer);
> +  }
> +
> +  return Status;
> +}
> +
> +
> +/**
> +  Clear capsule status variable.
> +
> +  @retval EFI_SUCCESS            The capsule status variable is cleared.
> +**/
> +EFI_STATUS
> +ClearCapsuleStatusVariable(
> +  VOID
> +  )
> +{
> +  EFI_STATUS                          Status;
> +  UINT32                              Index;
> +  CHAR16                              CapsuleVarName[20];
> +  CHAR16                              *TempVarName;
> +
> +  StrCpyS (CapsuleVarName, sizeof(CapsuleVarName)/sizeof(CapsuleVarName[0]),
> L"Capsule");
> +  TempVarName = CapsuleVarName + StrLen (CapsuleVarName);
> +  Index = 0;
> +
> +  while (TRUE) {
> +    UnicodeSPrint (TempVarName, 5 * sizeof(CHAR16), L"%04x", Index);
> +
> +    Status = gRT->SetVariable (
> +                    CapsuleVarName,
> +                    &gEfiCapsuleReportGuid,
> +                    EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS |
> EFI_VARIABLE_BOOTSERVICE_ACCESS,
> +                    0,
> +                    (VOID *)NULL
> +                    );
> +    if (EFI_ERROR(Status)) {
> +      //
> +      // There is no capsule variables, quit
> +      //
> +      break;
> +    }
> +
> +    Index++;
> +    if (Index > 0xFFFF) {
> +      break;
> +    }
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Get the active UEFI system partition from bootoption list.
> +
> +  @param[out] Fs    Simple File System protocol on the active UEFI system partition
> +
> +  @retval EFI_SUCCESS   active UEFI system partition found
> +**/
> +EFI_STATUS
> +GetEfiSysPartition(
> +  OUT EFI_SIMPLE_FILE_SYSTEM_PROTOCOL **Fs
> +  )
> +{
> +  EFI_STATUS                       Status;
> +  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL  *FsTemp;
> +  UINTN                            NoHandles;
> +  EFI_HANDLE                       *Handles;
> +  UINTN                            Index;
> +
> +  Handles = NULL;
> +
> +  //
> +  // search for EFI system partition protocol on Boot option device path
> +  //
> +  Status = gBS->LocateHandleBuffer(ByProtocol, &gEfiPartTypeSystemPartGuid, NULL,
> &NoHandles, &Handles);
> +  if (EFI_ERROR(Status)) {
> +    return Status;
> +  }
> +
> +  //
> +  // Skip BootOptions within FV
> +  //
> +  for (Index = 0; Index < NoHandles; Index++) {
> +    Status = gBS->HandleProtocol (Handles[Index], &gEfiSimpleFileSystemProtocolGuid,
> (VOID **)&FsTemp);
> +    if (!EFI_ERROR (Status)){
> +      *Fs = FsTemp;
> +      break;
> +    }
> +  }
> +  return Status;
> +}
> +
> +/**
> +  Copy a list of capsule images to the active UEFI system partition from bootoption
> list.
> +
> +  @param[in] CapsuleBuffer    An array of pointer to capsule images
> +  @param[in] FileSize         An array of UINTN to capsule images size
> +  @param[in] CapsuleNum       The count of capsule images
> +
> +  @retval EFI_SUCCESS   Capsule images are copied to the active UEFI system partition
> +**/
> +EFI_STATUS
> +CopyCapsuleToActiveEfiPartition(
> +  IN VOID                          **CapsuleBuffer,
> +  IN UINTN                         *FileSize,
> +  IN UINTN                         CapsuleNum
> +  )
> +{
> +  EFI_STATUS                       Status;
> +  CHAR16                           *CapsuleName;
> +  UINTN                            Index;
> +  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL  *Fs;
> +  EFI_FILE_HANDLE                  RootDir;
> +  EFI_FILE_HANDLE                  CapsuleDir;
> +  EFI_FILE_HANDLE                  DestHandle;
> +  UINTN                            DataSize;
> +  UINT64                           OsIndication;
> +
> +  RootDir      = NULL;
> +  CapsuleDir   = NULL;
> +
> +  Status = GetEfiSysPartition(&Fs);
> +  if (EFI_ERROR(Status)) {
> +    Print (L"Can not find active UEFI System Partition\n");
> +    return Status;
> +  }
> +
> +  Status = Fs->OpenVolume(Fs, &RootDir);
> +  if (EFI_ERROR(Status)) {
> +    goto EXIT;
> +  }
> +
> +  Status = RootDir->Open(
> +                      RootDir,
> +                      &CapsuleDir,
> +                      EFI_CAPSULE_FROM_FILE_DIR,
> +                      EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE,
> +                      EFI_FILE_DIRECTORY
> +                      );
> +  if (EFI_ERROR(Status)) {
> +    goto EXIT;
> +  }
> +
> +  //
> +  // Read the input files.
> +  //
> +  for (Index = 0; Index < CapsuleNum; Index++) {
> +    CapsuleName = Argv[CapsuleFirstIndex + Index];
> +    Status = CapsuleDir->Open(
> +                           CapsuleDir,
> +                           &DestHandle,
> +                           CapsuleName,
> +                           EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE |
> EFI_FILE_MODE_CREATE,
> +                           EFI_FILE_ARCHIVE
> +                           );
> +    if (EFI_ERROR(Status)) {
> +      Print(L"CapsuleApp: %s open error - %r\n", CapsuleName, Status);
> +      continue;
> +    }
> +
> +    DataSize = FileSize[Index];
> +    Status = DestHandle->Write(
> +                           DestHandle,
> +                           &DataSize,
> +                           CapsuleBuffer[Index]
> +                           );
> +    DestHandle->Close(DestHandle);
> +    if (EFI_ERROR(Status)) {
> +      Print(L"CapsuleApp: %s write error - %r, FileSize - 0x%x\n", CapsuleName,
> Status, FileSize[Index]);
> +    }
> +  }
> +
> +  Status = gRT->GetVariable (
> +                  L"OsIndications",
> +                  &gEfiGlobalVariableGuid,
> +                  NULL,
> +                  &DataSize,
> +                  (VOID *) &OsIndication
> +                  );
> +
> +  if (EFI_ERROR(Status) || DataSize != sizeof(OsIndication)) {
> +    OsIndication = 0;
> +  }
> +
> +  //
> +  // Set OsIndications Variable EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED bit
> +  //
> +  OsIndication |= EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED;
> +  Status = gRT->SetVariable (
> +                  L"OsIndications",
> +                  &gEfiGlobalVariableGuid,
> +                  EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS |
> +                  EFI_VARIABLE_BOOTSERVICE_ACCESS,
> +                  sizeof(OsIndication),
> +                  (VOID *)&OsIndication
> +                  );
> +
> +
> +EXIT:
> +  if (RootDir != NULL) {
> +    RootDir->Close(RootDir);
> +  }
> +
> +  if (CapsuleDir != NULL) {
> +    CapsuleDir->Close(CapsuleDir);
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  Build Gather list for a list of capsule images.
> +
> +  @param[in]  CapsuleBuffer    An array of pointer to capsule images
> +  @param[in]  FileSize         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                         *FileSize,
> +  IN UINTN                         CapsuleNum,
> +  OUT EFI_CAPSULE_BLOCK_DESCRIPTOR **BlockDescriptors
> +  )
> +{
> +  EFI_STATUS                    Status;
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR  *BlockDescriptors1;
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR  *BlockDescriptors2;
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR  *BlockDescriptorPre;
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR  *BlockDescriptorsHeader;
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR  *TempBlockPtr;
> +  UINT8                         *TempDataPtr;
> +  UINTN                         SizeLeft;
> +  UINTN                         Size;
> +  INT32                         Count;
> +  INT32                         Number;
> +  UINTN                         Index;
> +
> +  TempBlockPtr           = NULL;
> +  BlockDescriptors1      = NULL;
> +  BlockDescriptors2      = NULL;
> +  BlockDescriptorPre     = NULL;
> +  BlockDescriptorsHeader = NULL;
> +
> +  for (Index = 0; Index < CapsuleNum; Index++) {
> +    //
> +    // Allocate memory for the descriptors.
> +    //
> +    if (NumberOfDescriptors == 1) {
> +      Count = 2;
> +    } else {
> +      Count = (INT32)(NumberOfDescriptors + 2) / 2;
> +    }
> +
> +    Size               = Count * sizeof (EFI_CAPSULE_BLOCK_DESCRIPTOR);
> +    BlockDescriptors1  = AllocateRuntimeZeroPool (Size);
> +    if (BlockDescriptors1 == NULL) {
> +      Print (L"CapsuleApp: failed to allocate memory for descriptors\n");
> +      Status = EFI_OUT_OF_RESOURCES;
> +      goto ERREXIT;
> +    } else {
> +      Print (L"CapsuleApp: creating capsule descriptors at 0x%X\n", (UINTN)
> BlockDescriptors1);
> +      Print (L"CapsuleApp: capsule data starts          at 0x%X with size 0x%X\n",
> (UINTN) CapsuleBuffer, FileSize);
> +    }
> +
> +    //
> +    // Record descirptor header
> +    //
> +    if (Index == 0) {
> +      BlockDescriptorsHeader = BlockDescriptors1;
> +    }
> +
> +    if (BlockDescriptorPre != NULL) {
> +      BlockDescriptorPre->Union.ContinuationPointer = (UINTN) BlockDescriptors1;
> +      BlockDescriptorPre->Length = 0;
> +    }
> +
> +    //
> +    // Fill them in
> +    //
> +    TempBlockPtr  = BlockDescriptors1;
> +    TempDataPtr   = CapsuleBuffer[Index];
> +    SizeLeft      = FileSize[Index];
> +    for (Number = 0; (Number < Count - 1) && (SizeLeft != 0); Number++) {
> +      //
> +      // Divide remaining data in half
> +      //
> +      if (NumberOfDescriptors != 1) {
> +        if (SizeLeft == 1) {
> +          Size = 1;
> +        } else {
> +          Size = SizeLeft / 2;
> +        }
> +      } else {
> +        Size = SizeLeft;
> +      }
> +      TempBlockPtr->Union.DataBlock    = (UINTN)TempDataPtr;
> +      TempBlockPtr->Length  = Size;
> +      Print (L"CapsuleApp: capsule block/size              0x%X/0x%X\n", (UINTN)
> TempDataPtr, Size);
> +      SizeLeft -= Size;
> +      TempDataPtr += Size;
> +      TempBlockPtr++;
> +    }
> +
> +    //
> +    // Allocate the second list, point the first block's last entry to point
> +    // to this one, and fill this one in. Worst case is that the previous
> +    // list only had one element that pointed here, so we need at least two
> +    // elements -- one to point to all the data, another to terminate the list.
> +    //
> +    if ((NumberOfDescriptors != 1) && (SizeLeft != 0)) {
> +      Count = (INT32)(NumberOfDescriptors + 2) - Count;
> +      if (Count == 1) {
> +        Count++;
> +      }
> +
> +      Size              = Count * sizeof (EFI_CAPSULE_BLOCK_DESCRIPTOR);
> +      BlockDescriptors2 = AllocateRuntimeZeroPool (Size);
> +      if (BlockDescriptors2 == NULL) {
> +        Print (L"CapsuleApp: failed to allocate memory for descriptors\n");
> +        Status = EFI_OUT_OF_RESOURCES;
> +        goto ERREXIT;
> +      }
> +
> +      //
> +      // Point the first list's last element to point to this second list.
> +      //
> +      TempBlockPtr->Union.ContinuationPointer   = (UINTN) BlockDescriptors2;
> +
> +      TempBlockPtr->Length  = 0;
> +      TempBlockPtr = BlockDescriptors2;
> +      for (Number = 0; Number < Count - 1; Number++) {
> +        //
> +        // If second-to-last one, then dump rest to this element
> +        //
> +        if (Number == (Count - 2)) {
> +          Size = SizeLeft;
> +        } else {
> +          //
> +          // Divide remaining data in half
> +          //
> +          if (SizeLeft == 1) {
> +            Size = 1;
> +          } else {
> +            Size = SizeLeft / 2;
> +          }
> +        }
> +
> +        TempBlockPtr->Union.DataBlock    = (UINTN)TempDataPtr;
> +        TempBlockPtr->Length  = Size;
> +        Print (L"CapsuleApp: capsule block/size              0x%X/0x%X\n", (UINTN)
> TempDataPtr, Size);
> +        SizeLeft -= Size;
> +        TempDataPtr += Size;
> +        TempBlockPtr++;
> +        if (SizeLeft == 0) {
> +          break;
> +        }
> +      }
> +    }
> +
> +    BlockDescriptorPre = TempBlockPtr;
> +    BlockDescriptors1  = NULL;
> +  }
> +
> +  //
> +  // Null-terminate.
> +  //
> +  if (TempBlockPtr != NULL) {
> +    TempBlockPtr->Union.ContinuationPointer    = (UINTN)NULL;
> +    TempBlockPtr->Length  = 0;
> +    *BlockDescriptors = BlockDescriptorsHeader;
> +  }
> +
> +  return EFI_SUCCESS;
> +
> +ERREXIT:
> +  if (BlockDescriptors1 != NULL) {
> +    FreePool(BlockDescriptors1);
> +  }
> +
> +  if (BlockDescriptors2 != NULL) {
> +    FreePool(BlockDescriptors2);
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  Clear the Gather list for a list of capsule images.
> +
> +  @param[in]  BlockDescriptors The block descriptors for the capsule images
> +  @param[in]  CapsuleNum       The count of capsule images
> +**/
> +VOID
> +CleanGatherList(
> +  IN EFI_CAPSULE_BLOCK_DESCRIPTOR   *BlockDescriptors,
> +  IN UINTN                          CapsuleNum
> +  )
> +{
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR   *TempBlockPtr;
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR   *TempBlockPtr1;
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR   *TempBlockPtr2;
> +  UINTN                          Index;
> +
> +  if (BlockDescriptors != NULL) {
> +    TempBlockPtr1 = BlockDescriptors;
> +    while (1){
> +      TempBlockPtr = TempBlockPtr1;
> +      for (Index = 0; Index < CapsuleNum; Index++) {
> +        if (TempBlockPtr[Index].Length == 0) {
> +          break;
> +        }
> +      }
> +
> +      if (TempBlockPtr[Index].Union.ContinuationPointer == (UINTN)NULL) {
> +        break;
> +      }
> +
> +      TempBlockPtr2 = (VOID *) ((UINTN) TempBlockPtr->Union.ContinuationPointer);
> +      FreePool(TempBlockPtr1);
> +      TempBlockPtr1 = TempBlockPtr2;
> +    }
> +  }
> +}
> +
> +/**
> +  Print APP usage.
> +**/
> +VOID
> +PrintUsage (
> +  VOID
> +  )
> +{
> +  Print(L"CapsuleApp:  usage\n");
> +  Print(L"  CapsuleApp [-F] <Capsule...> [-NR]\n");
> +  Print(L"  CapsuleApp -S\n");
> +  Print(L"  CapsuleApp -C\n");
> +  Print(L"  CapsuleApp -P\n");
> +  Print(L"  CapsuleApp -E\n");
> +  Print(L"  CapsuleApp -G <BMP> -O <Capsule>\n");
> +  Print(L"  CapsuleApp -N <Capsule> -O <NestedCapsule>\n");
> +  Print(L"  CapsuleApp -D|-DS <Capsule>\n");
> +  Print(L"Parameter:\n");
> +  Print(L"  -F:  Put capsule file to disk.\n");
> +  Print(L"       No -F means to put capsule file in memory.\n");
> +  Print(L"  -NR: No Reset.\n");
> +  Print(L"  -S:  Dump capsule status.\n");
> +  Print(L"  -C:  Clear capsule status.\n");
> +  Print(L"  -P:  Dump FMP protocol info.\n");
> +  Print(L"  -E:  Dump ESRT table info.\n");
> +  Print(L"  -G:  Input BMP file name\n");
> +  Print(L"  -N:  Append Capsule Header accroding to Windows Firmware Update\n");
> +  Print(L"  -O:  Output Capsule file name\n");
> +  Print(L"  -D:  Dump Capsule\n");
> +  Print(L"  -DS: Dump Capsule with System FMP format\n");
> +}
> +
> +/**
> +  Update Capsule image.
> +
> +  @param[in]  ImageHandle     The image handle.
> +  @param[in]  SystemTable     The system table.
> +
> +  @retval EFI_SUCCESS            Command completed successfully.
> +  @retval EFI_INVALID_PARAMETER  Command usage error.
> +  @retval EFI_NOT_FOUND          The input file can't be found.
> +**/
> +EFI_STATUS
> +EFIAPI
> +UefiMain (
> +  IN EFI_HANDLE        ImageHandle,
> +  IN EFI_SYSTEM_TABLE  *SystemTable
> +  )
> +{
> +  EFI_STATUS                    Status;
> +  UINTN                         FileSize[MAX_CAPSULE_NUM];
> +  VOID                          *CapsuleBuffer[MAX_CAPSULE_NUM];
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR  *BlockDescriptors;
> +  EFI_CAPSULE_HEADER             *CapsuleHeaderArray[MAX_CAPSULE_NUM + 1];
> +  UINT64                         MaxCapsuleSize;
> +  EFI_RESET_TYPE                 ResetType;
> +  BOOLEAN                        NeedReset;
> +  BOOLEAN                        NoReset;
> +  BOOLEAN                        NeedCopyOnDisk;
> +  CHAR16                         *CapsuleName;
> +  UINTN                          CapsuleNum;
> +  UINTN                          Index;
> +
> +  Status = GetArg();
> +  if (EFI_ERROR(Status)) {
> +    PrintUsage();
> +    return Status;
> +  }
> +  if (Argc < 2) {
> +    PrintUsage();
> +    CleanArg();
> +    return EFI_INVALID_PARAMETER;
> +  }
> +  if ((StrCmp(Argv[1], L"-D") == 0) ||
> +      (StrCmp(Argv[1], L"-DS") == 0)) {
> +    Status = DumpCapsule();
> +    CleanArg();
> +    return Status;
> +  }
> +  if (StrCmp(Argv[1], L"-G") == 0) {
> +    Status = CreateBmpFmp();
> +    CleanArg();
> +    return Status;
> +  }
> +  if (StrCmp(Argv[1], L"-N") == 0) {
> +    Status = CreateNestedFmp();
> +    CleanArg();
> +    return Status;
> +  }
> +  if (StrCmp(Argv[1], L"-S") == 0) {
> +    Status = DmpCapsuleStatusVariable();
> +    CleanArg();
> +    return EFI_SUCCESS;
> +  }
> +  if (StrCmp(Argv[1], L"-C") == 0) {
> +    Status = ClearCapsuleStatusVariable();
> +    CleanArg();
> +    return Status;
> +  }
> +  if (StrCmp(Argv[1], L"-P") == 0) {
> +    DumpFmpData();
> +    CleanArg();
> +    return EFI_SUCCESS;
> +  }
> +  if (StrCmp(Argv[1], L"-E") == 0) {
> +    DumpEsrtData();
> +    CleanArg();
> +    return EFI_SUCCESS;
> +  }
> +  if (StrCmp(Argv[1], L"-F") == 0) {
> +    NeedCopyOnDisk = TRUE;
> +    CapsuleFirstIndex = 2;
> +  } else {
> +    NeedCopyOnDisk = FALSE;
> +    CapsuleFirstIndex = 1;
> +  }
> +  if (StrCmp(Argv[Argc - 1], L"-NR") == 0) {
> +    NoReset = TRUE;
> +    CapsuleLastIndex = Argc - 2;
> +  } else {
> +    NoReset = FALSE;
> +    CapsuleLastIndex = Argc - 1;
> +  }
> +  CapsuleNum = CapsuleLastIndex - CapsuleFirstIndex + 1;
> +
> +  if (CapsuleFirstIndex > CapsuleLastIndex) {
> +    Print(L"CapsuleApp: NO capsule image.\n");
> +    CleanArg();
> +    return EFI_UNSUPPORTED;
> +  }
> +  if (CapsuleNum > MAX_CAPSULE_NUM) {
> +    Print(L"CapsuleApp: Too many capsule images.\n");
> +    CleanArg();
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  ZeroMem(&CapsuleBuffer, sizeof(CapsuleBuffer));
> +  ZeroMem(&FileSize, sizeof(FileSize));
> +  BlockDescriptors = NULL;
> +
> +  for (Index = 0; Index < CapsuleNum; Index++) {
> +    CapsuleName = Argv[CapsuleFirstIndex + Index];
> +    Status = ReadFileToBuffer(CapsuleName, &FileSize[Index], &CapsuleBuffer[Index]);
> +    if (EFI_ERROR(Status)) {
> +      Print(L"CapsuleApp: capsule image (%s) is not found.\n", CapsuleName);
> +      goto Done;
> +    }
> +  }
> +
> +  if (NeedCopyOnDisk) {
> +    Status = CopyCapsuleToActiveEfiPartition(CapsuleBuffer, FileSize, CapsuleNum);
> +  } else {
> +    //
> +    // Every capsule use 2 descriptor 1 for data 1 for end
> +    //
> +    Status = BuildGatherList(CapsuleBuffer, FileSize, CapsuleNum, &BlockDescriptors);
> +  }
> +  if (EFI_ERROR(Status)) {
> +    goto Done;
> +  }
> +
> +  //
> +  // Call the runtime service capsule.
> +  //
> +  NeedReset = FALSE;
> +  for (Index = 0; Index < CapsuleNum; Index++) {
> +    CapsuleHeaderArray[Index] = (EFI_CAPSULE_HEADER *) CapsuleBuffer[Index];
> +    if ((CapsuleHeaderArray[Index]->Flags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET) != 0)
> {
> +      NeedReset = TRUE;
> +    }
> +  }
> +  CapsuleHeaderArray[CapsuleNum] = NULL;
> +  if (NoReset) {
> +    NeedReset = FALSE;
> +  }
> +
> +  //
> +  // Inquire platform capability of UpdateCapsule.
> +  //
> +  Status = gRT->QueryCapsuleCapabilities (CapsuleHeaderArray, CapsuleNum,
> &MaxCapsuleSize, &ResetType);
> +  if (EFI_ERROR(Status)) {
> +    Print (L"CapsuleApp: failed to query capsule capability - %r\n", Status);
> +    goto Done;
> +  }
> +
> +  for (Index = 0; Index < CapsuleNum; Index++) {
> +    if (FileSize[Index] > MaxCapsuleSize) {
> +      Print (L"CapsuleApp: capsule is too large to update, %ld is allowed\n",
> MaxCapsuleSize);
> +      Status = EFI_UNSUPPORTED;
> +      goto Done;
> +    }
> +  }
> +
> +  //
> +  // Check whether the input capsule image has the flag of persist across system
> reset.
> +  //
> +  if (NeedReset) {
> +    Status = gRT->UpdateCapsule(CapsuleHeaderArray,CapsuleNum,(UINTN)
> BlockDescriptors);
> +    if (Status != EFI_SUCCESS) {
> +      Print (L"CapsuleApp: failed to update capsule - %r\n", Status);
> +      goto Done;
> +    }
> +    //
> +    // For capsule who has reset flag, after calling UpdateCapsule service,triger a
> +    // system reset to process capsule persist across a system reset.
> +    //
> +    gRT->ResetSystem (ResetType, EFI_SUCCESS, 0, NULL);
> +  } else {
> +    //
> +    // For capsule who has no reset flag, only call UpdateCapsule Service without a
> +    // system reset. The service will process the capsule immediately.
> +    //
> +    Status = gRT->UpdateCapsule (CapsuleHeaderArray,CapsuleNum,(UINTN)
> BlockDescriptors);
> +    if (Status != EFI_SUCCESS) {
> +      Print (L"CapsuleApp: failed to update capsule - %r\n", Status);
> +    }
> +  }
> +
> +  Status = EFI_SUCCESS;
> +
> +Done:
> +  for (Index = 0; Index < CapsuleNum; Index++) {
> +    if (CapsuleBuffer[Index] != NULL) {
> +      FreePool (CapsuleBuffer[Index]);
> +    }
> +  }
> +
> +  CleanGatherList(BlockDescriptors, CapsuleNum);
> +  CleanArg();
> +
> +  return Status;
> +}
> diff --git a/MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf
> b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf
> new file mode 100644
> index 0000000..7ee44fc
> --- /dev/null
> +++ b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf
> @@ -0,0 +1,71 @@
> +##  @file
> +#  A shell application that triggers capsule update process.
> +#
> +# This application can trigger capsule update process. It can also
> +# generate capsule image, or dump capsule variable information.
> +#
> +#  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
> +#  This program and the accompanying materials
> +#  are licensed and made available under the terms and conditions of the BSD License
> +#  which accompanies this distribution.  The full text of the license may be found at
> +#  http://opensource.org/licenses/bsd-license.php
> +#
> +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +#
> +##
> +
> +[Defines]
> +  INF_VERSION                    = 0x00010006
> +  BASE_NAME                      = CapsuleApp
> +  MODULE_UNI_FILE                = CapsuleApp.uni
> +  FILE_GUID                      = 4CEF31DA-8682-4274-9CC4-AEE7516A5E7B
> +  MODULE_TYPE                    = UEFI_APPLICATION
> +  VERSION_STRING                 = 1.0
> +  ENTRY_POINT                    = UefiMain
> +
> +#
> +# The following information is for reference only and not required by the build tools.
> +#
> +#  VALID_ARCHITECTURES           = IA32 X64
> +#
> +
> +[Sources]
> +  CapsuleApp.c
> +  CapsuleDump.c
> +  AppSupport.c
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +
> +[Guids]
> +  gEfiFileInfoGuid
> +  gEfiPartTypeSystemPartGuid
> +  gEfiGlobalVariableGuid
> +  gEfiCapsuleReportGuid
> +  gEfiFmpCapsuleGuid
> +  gWindowsUxCapsuleGuid
> +  gEfiCertTypeRsa2048Sha256Guid
> +  gEfiCertPkcs7Guid
> +  gEfiSystemResourceTableGuid
> +
> +[Protocols]
> +  gEfiLoadedImageProtocolGuid
> +  gEfiSimpleFileSystemProtocolGuid
> +  gEfiGraphicsOutputProtocolGuid
> +  gEfiFirmwareManagementProtocolGuid
> +
> +[LibraryClasses]
> +  BaseLib
> +  UefiApplicationEntryPoint
> +  DebugLib
> +  MemoryAllocationLib
> +  UefiBootServicesTableLib
> +  UefiRuntimeServicesTableLib
> +  UefiLib
> +  PrintLib
> +  EdkiiSystemCapsuleLib
> +
> +[UserExtensions.TianoCore."ExtraFiles"]
> +  CapsuleAppExtra.uni
> diff --git a/MdeModulePkg/Application/CapsuleApp/CapsuleApp.uni
> b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.uni
> new file mode 100644
> index 0000000..54d6e12
> --- /dev/null
> +++ b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.uni
> @@ -0,0 +1,22 @@
> +// /** @file
> +// A shell application that triggers capsule update process.
> +//
> +// This application can trigger capsule update process. It can also
> +// generate capsule image, or dump capsule variable information.
> +//
> +// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
> +//
> +// This program and the accompanying materials
> +// are licensed and made available under the terms and conditions of the BSD License
> +// which accompanies this distribution. The full text of the license may be found at
> +// http://opensource.org/licenses/bsd-license.php
> +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +//
> +// **/
> +
> +
> +#string STR_MODULE_ABSTRACT             #language en-US "A shell application that
> triggers capsule update process."
> +
> +#string STR_MODULE_DESCRIPTION          #language en-US "This application can trigger
> capsule update process. It can also generate capsule image, or dump capsule variable
> information."
> +
> diff --git a/MdeModulePkg/Application/CapsuleApp/CapsuleAppExtra.uni
> b/MdeModulePkg/Application/CapsuleApp/CapsuleAppExtra.uni
> new file mode 100644
> index 0000000..b5a8840
> --- /dev/null
> +++ b/MdeModulePkg/Application/CapsuleApp/CapsuleAppExtra.uni
> @@ -0,0 +1,19 @@
> +// /** @file
> +// CapsuleApp Localized Strings and Content
> +//
> +// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
> +//
> +// This program and the accompanying materials
> +// are licensed and made available under the terms and conditions of the BSD License
> +// which accompanies this distribution. The full text of the license may be found at
> +// http://opensource.org/licenses/bsd-license.php
> +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +//
> +// **/
> +
> +#string STR_PROPERTIES_MODULE_NAME
> +#language en-US
> +"Capsule Application"
> +
> +
> diff --git a/MdeModulePkg/Application/CapsuleApp/CapsuleDump.c
> b/MdeModulePkg/Application/CapsuleApp/CapsuleDump.c
> new file mode 100644
> index 0000000..c56f41f
> --- /dev/null
> +++ b/MdeModulePkg/Application/CapsuleApp/CapsuleDump.c
> @@ -0,0 +1,840 @@
> +/** @file
> +  Dump Capsule image information.
> +
> +  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the BSD License
> +  which accompanies this distribution.  The full text of the license may be found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +
> +**/
> +
> +#include <PiDxe.h>
> +#include <Library/BaseLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/UefiRuntimeServicesTableLib.h>
> +#include <Library/UefiLib.h>
> +#include <Library/PrintLib.h>
> +#include <Library/EdkiiSystemCapsuleLib.h>
> +#include <Protocol/FirmwareManagement.h>
> +#include <Guid/ImageAuthentication.h>
> +#include <Guid/EdkiiSystemFmpCapsule.h>
> +#include <Guid/CapsuleReport.h>
> +#include <Guid/SystemResourceTable.h>
> +#include <Guid/FmpCapsule.h>
> +#include <IndustryStandard/WindowsUxCapsule.h>
> +
> +/**
> +  Read a file.
> +
> +  @param FileName        The file to be read.
> +  @param BufferSize      The file buffer size
> +  @param Buffer          The file buffer
> +
> +  @retval EFI_SUCCESS    Read file successfully
> +  @retval EFI_NOT_FOUND  File not found
> +**/
> +EFI_STATUS
> +ReadFileToBuffer(
> +  IN  CHAR16                               *FileName,
> +  OUT UINTN                                *BufferSize,
> +  OUT VOID                                 **Buffer
> +  );
> +
> +extern UINTN  Argc;
> +extern CHAR16 *Argv[];
> +
> +/**
> +  Dump UX capsule information.
> +
> +  @param CapsuleHeader      The UX capsule header
> +**/
> +VOID
> +DumpUxCapsule(
> +  IN EFI_CAPSULE_HEADER  *CapsuleHeader
> +  )
> +{
> +  EFI_DISPLAY_CAPSULE                           *DisplayCapsule;
> +  DisplayCapsule = (EFI_DISPLAY_CAPSULE *)CapsuleHeader;
> +  Print(L"[UxCapusule]\n");
> +  Print(L"CapsuleHeader:\n");
> +  Print(L"  CapsuleGuid      - %g\n", &DisplayCapsule->CapsuleHeader.CapsuleGuid);
> +  Print(L"  HeaderSize       - 0x%x\n", DisplayCapsule->CapsuleHeader.HeaderSize);
> +  Print(L"  Flags            - 0x%x\n", DisplayCapsule->CapsuleHeader.Flags);
> +  Print(L"  CapsuleImageSize - 0x%x\n", DisplayCapsule-
> >CapsuleHeader.CapsuleImageSize);
> +  Print(L"ImagePayload:\n");
> +  Print(L"  Version          - 0x%x\n", DisplayCapsule->ImagePayload.Version);
> +  Print(L"  Checksum         - 0x%x\n", DisplayCapsule->ImagePayload.Checksum);
> +  Print(L"  ImageType        - 0x%x\n", DisplayCapsule->ImagePayload.ImageType);
> +  Print(L"  Mode             - 0x%x\n", DisplayCapsule->ImagePayload.Mode);
> +  Print(L"  OffsetX          - 0x%x\n", DisplayCapsule->ImagePayload.OffsetX);
> +  Print(L"  OffsetY          - 0x%x\n", DisplayCapsule->ImagePayload.OffsetY);
> +}
> +
> +/**
> +  Dump FMP image authentication information.
> +
> +  @param Image      The FMP capsule image
> +  @param ImageSize  The size of the FMP capsule image in bytes.
> +
> +  @return the size of FMP authentication.
> +**/
> +UINTN
> +DumpImageAuthentication(
> +  IN VOID   *Image,
> +  IN UINTN  ImageSize
> +  )
> +{
> +  EFI_FIRMWARE_IMAGE_AUTHENTICATION             *ImageAuthentication;
> +
> +  ImageAuthentication = Image;
> +  if (CompareGuid(&ImageAuthentication->AuthInfo.CertType, &gEfiCertPkcs7Guid) ||
> +      CompareGuid(&ImageAuthentication->AuthInfo.CertType,
> &gEfiCertTypeRsa2048Sha256Guid)) {
> +    Print(L"[ImageAuthentication]\n");
> +    Print(L"  MonotonicCount   - 0x%lx\n", ImageAuthentication->MonotonicCount);
> +    Print(L"WIN_CERTIFICATE:\n");
> +    Print(L"  dwLength         - 0x%x\n", ImageAuthentication->AuthInfo.Hdr.dwLength);
> +    Print(L"  wRevision        - 0x%x\n", ImageAuthentication-
> >AuthInfo.Hdr.wRevision);
> +    Print(L"  wCertificateType - 0x%x\n", ImageAuthentication-
> >AuthInfo.Hdr.wCertificateType);
> +    Print(L"  CertType         - %g\n", &ImageAuthentication->AuthInfo.CertType);
> +    return sizeof(ImageAuthentication->MonotonicCount) + ImageAuthentication-
> >AuthInfo.Hdr.dwLength;
> +  } else {
> +    return 0;
> +  }
> +}
> +
> +/**
> +  Dump EDKII system FMP capsule.
> +
> +  @param Image      The EDKII system FMP capsule.
> +  @param ImageSize  The size of the EDKII system FMP capsule in bytes.
> +**/
> +VOID
> +DumpEdkiiSystemFmpCapsule(
> +  IN VOID   *Image,
> +  IN UINTN  ImageSize
> +  )
> +{
> +  UINTN                                         ImageOffset;
> +  VOID                                          *BiosImage;
> +  UINTN                                         BiosImageSize;
> +  BOOLEAN                                       Result;
> +  EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR        *TempImageFmpInfo;
> +  EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR        *ImageFmpInfo;
> +  UINTN                                         ImageFmpInfoSize;
> +
> +  //
> +  // We do not know if there is EFI_FIRMWARE_IMAGE_AUTHENTICATION.
> +  // so just *try* to parse it
> +  //
> +  ImageOffset = DumpImageAuthentication(Image, ImageSize);
> +  Image = (UINT8 *)Image + ImageOffset;
> +  ImageSize -= ImageOffset;
> +  Print(L"[Image]\n");
> +  Print(L"  ImageSize   - 0x%x\n", ImageSize);
> +
> +  Result = ExtractConfigImage(Image, ImageSize, &BiosImage, &BiosImageSize);
> +  if (Result) {
> +    Print(L"  ConfigFileSize  - 0x%x\n", BiosImageSize);
> +  }
> +  Result = ExtractDriverFvImage(Image, ImageSize, &BiosImage, &BiosImageSize);
> +  if (Result) {
> +    Print(L"  DriverFvSize    - 0x%x\n", BiosImageSize);
> +  }
> +  Result = ExtractSystemFirmwareImage(Image, ImageSize, &BiosImage, &BiosImageSize);
> +  if (Result) {
> +    Print(L"  BiosImageSize   - 0x%x\n", BiosImageSize);
> +  }
> +  Result = ExtractSystemFirmwareImageFmpInfo(BiosImage, BiosImageSize,
> &TempImageFmpInfo, &ImageFmpInfoSize);
> +  if (Result) {
> +    ImageFmpInfo = AllocateCopyPool(ImageFmpInfoSize, TempImageFmpInfo);
> +    if (ImageFmpInfo != NULL) {
> +      Print(L"[ImageFmpInfo]\n");
> +      Print(L"  Signature                      - 0x%x\n", ImageFmpInfo->Signature);
> +      Print(L"  HeaderLength                   - 0x%x\n", ImageFmpInfo->HeaderLength);
> +      Print(L"  Length                         - 0x%x\n", ImageFmpInfo->Length);
> +      Print(L"  PackageVersion                 - 0x%x\n", ImageFmpInfo-
> >PackageVersion);
> +      Print(L"  PackageVersionNameStringOffset - 0x%x\n", ImageFmpInfo-
> >PackageVersionNameStringOffset);
> +      if (ImageFmpInfo->PackageVersionNameStringOffset != 0) {
> +        Print(L"                                 - %s\n", (UINT8 *)ImageFmpInfo +
> ImageFmpInfo->PackageVersionNameStringOffset);
> +      }
> +      Print(L"  ImageIndex                     - 0x%x\n", ImageFmpInfo->ImageIndex);
> +      Print(L"  ImageTypeId                    - %g\n", &ImageFmpInfo->ImageTypeId);
> +      Print(L"  ImageId                        - 0x%lx\n", ImageFmpInfo->ImageId);
> +      Print(L"  ImageIdNameStringOffset        - 0x%x\n", ImageFmpInfo-
> >ImageIdNameStringOffset);
> +      if (ImageFmpInfo->ImageIdNameStringOffset != 0) {
> +        Print(L"                                 - %s\n", (UINT8 *)ImageFmpInfo +
> ImageFmpInfo->ImageIdNameStringOffset);
> +      }
> +      Print(L"  Version                        - 0x%x\n", ImageFmpInfo->Version);
> +      Print(L"  VersionNameStringOffset        - 0x%x\n", ImageFmpInfo-
> >VersionNameStringOffset);
> +      if (ImageFmpInfo->VersionNameStringOffset != 0) {
> +        Print(L"                                 - %s\n", (UINT8 *)ImageFmpInfo +
> ImageFmpInfo->VersionNameStringOffset);
> +      }
> +      Print(L"  Size                           - 0x%lx\n", ImageFmpInfo->Size);
> +      Print(L"  AttributesSupported            - 0x%lx\n", ImageFmpInfo-
> >AttributesSupported);
> +      Print(L"  AttributesSetting              - 0x%lx\n", ImageFmpInfo-
> >AttributesSetting);
> +      Print(L"  Compatibilities                - 0x%lx\n", ImageFmpInfo-
> >Compatibilities);
> +      Print(L"  LowestSupportedImageVersion    - 0x%x\n", ImageFmpInfo-
> >LowestSupportedImageVersion);
> +      Print(L"  LastAttemptVersion             - 0x%x\n", ImageFmpInfo-
> >LastAttemptVersion);
> +      Print(L"  LastAttemptStatus              - 0x%x\n", ImageFmpInfo-
> >LastAttemptStatus);
> +      Print(L"  HardwareInstance               - 0x%lx\n", ImageFmpInfo-
> >HardwareInstance);
> +      Print(L"  Version                        - 0x%x\n", ImageFmpInfo->Version);
> +      FreePool(ImageFmpInfo);
> +    }
> +  }
> +}
> +
> +/**
> +  Dump a non-nested FMP capsule.
> +
> +  @param  CapsuleHeader  A pointer to CapsuleHeader
> +  @param  IsSystemFmp    If it is a system FMP
> +**/
> +VOID
> +DumpFmpCapsule(
> +  IN EFI_CAPSULE_HEADER  *CapsuleHeader,
> +  IN BOOLEAN             IsSystemFmp
> +  )
> +{
> +  EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER        *FmpCapsuleHeader;
> +  UINT64                                        *ItemOffsetList;
> +  UINTN                                         Index;
> +  UINTN                                         Count;
> +  EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER  *FmpImageHeader;
> +  VOID                                          *Image;
> +
> +  Print(L"[FmpCapusule]\n");
> +  Print(L"CapsuleHeader:\n");
> +  Print(L"  CapsuleGuid      - %g\n", &CapsuleHeader->CapsuleGuid);
> +  Print(L"  HeaderSize       - 0x%x\n", CapsuleHeader->HeaderSize);
> +  Print(L"  Flags            - 0x%x\n", CapsuleHeader->Flags);
> +  Print(L"  CapsuleImageSize - 0x%x\n", CapsuleHeader->CapsuleImageSize);
> +
> +  FmpCapsuleHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *)((UINT8 *)CapsuleHeader
> + CapsuleHeader->HeaderSize);
> +  ItemOffsetList = (UINT64 *)(FmpCapsuleHeader + 1);
> +  Print(L"FmpHeader:\n");
> +  Print(L"  Version             - 0x%x\n", FmpCapsuleHeader->Version);
> +  Print(L"  EmbeddedDriverCount - 0x%x\n", FmpCapsuleHeader->EmbeddedDriverCount);
> +  Print(L"  PayloadItemCount    - 0x%x\n", FmpCapsuleHeader->PayloadItemCount);
> +  Count = FmpCapsuleHeader->EmbeddedDriverCount + FmpCapsuleHeader->PayloadItemCount;
> +  for (Index = 0; Index < Count; Index++) {
> +    Print(L"  Offset[%d]           - 0x%x\n", Index, ItemOffsetList[Index]);
> +  }
> +
> +  for (Index = FmpCapsuleHeader->EmbeddedDriverCount; Index < Count; Index++) {
> +    Print(L"FmpPayload[%d] ImageHeader:\n", Index);
> +    FmpImageHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *)((UINT8
> *)FmpCapsuleHeader + ItemOffsetList[Index]);
> +    Print(L"  Version                - 0x%x\n", FmpImageHeader->Version);
> +    Print(L"  UpdateImageTypeId      - %g\n", &FmpImageHeader->UpdateImageTypeId);
> +    Print(L"  UpdateImageIndex       - 0x%x\n", FmpImageHeader->UpdateImageIndex);
> +    Print(L"  UpdateImageSize        - 0x%x\n", FmpImageHeader->UpdateImageSize);
> +    Print(L"  UpdateVendorCodeSize   - 0x%x\n", FmpImageHeader->UpdateVendorCodeSize);
> +    if (FmpImageHeader->Version >=
> EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {
> +      Print(L"  UpdateHardwareInstance - 0x%lx\n", FmpImageHeader-
> >UpdateHardwareInstance);
> +    }
> +    if (FmpImageHeader->Version >=
> EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {
> +      Image = (UINT8 *)(FmpImageHeader + 1);
> +    }  else {
> +      Image = (UINT8 *)FmpImageHeader +
> OFFSET_OF(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER, UpdateHardwareInstance);
> +    }
> +    if (IsSystemFmp) {
> +      DumpEdkiiSystemFmpCapsule(Image, FmpImageHeader->UpdateImageSize);
> +    }
> +  }
> +}
> +
> +/**
> +  Return if there is a FMP header below capsule header.
> +
> +  @param[in] CapsuleHeader A pointer to EFI_CAPSULE_HEADER
> +
> +  @retval TRUE  There is a FMP header below capsule header.
> +  @retval FALSE There is not a FMP header below capsule header
> +**/
> +BOOLEAN
> +IsNestedFmpCapsule(
> +  IN EFI_CAPSULE_HEADER         *CapsuleHeader
> +  )
> +{
> +  EFI_STATUS                 Status;
> +  EFI_SYSTEM_RESOURCE_TABLE  *Esrt;
> +  EFI_SYSTEM_RESOURCE_ENTRY  *EsrtEntry;
> +  UINTN                      Index;
> +  BOOLEAN                    EsrtGuidFound;
> +  EFI_CAPSULE_HEADER         *NestedCapsuleHeader;
> +  UINTN                      NestedCapsuleSize;
> +
> +  //
> +  // Check ESRT
> +  //
> +  EsrtGuidFound = FALSE;
> +  Status = EfiGetSystemConfigurationTable(&gEfiSystemResourceTableGuid, (VOID
> **)&Esrt);
> +  if (!EFI_ERROR(Status)) {
> +    EsrtEntry = (VOID *)(Esrt + 1);
> +    for (Index = 0; Index < Esrt->FwResourceCount; Index++, EsrtEntry++) {
> +      if (CompareGuid(&EsrtEntry->FwClass, &CapsuleHeader->CapsuleGuid)) {
> +        EsrtGuidFound = TRUE;
> +        break;
> +      }
> +    }
> +  }
> +
> +  if (!EsrtGuidFound) {
> +    return FALSE;
> +  }
> +
> +  //
> +  // Check nested capsule header
> +  // FMP GUID after ESRT one
> +  //
> +  NestedCapsuleHeader = (EFI_CAPSULE_HEADER *)((UINT8 *)CapsuleHeader + CapsuleHeader-
> >HeaderSize);
> +  NestedCapsuleSize = (UINTN)CapsuleHeader + CapsuleHeader->HeaderSize -
> (UINTN)NestedCapsuleHeader;
> +  if (NestedCapsuleSize < sizeof(EFI_CAPSULE_HEADER)) {
> +    return FALSE;
> +  }
> +  if (!CompareGuid(&NestedCapsuleHeader->CapsuleGuid, &gEfiFmpCapsuleGuid)) {
> +    return FALSE;
> +  }
> +  return TRUE;
> +}
> +
> +/**
> +  Dump capsule information
> +
> +  @retval EFI_SUCCESS            The capsule information is dumped.
> +  @retval EFI_UNSUPPORTED        Input parameter is not valid.
> +**/
> +EFI_STATUS
> +DumpCapsule(
> +  VOID
> +  )
> +{
> +  CHAR16                                        *CapsuleName;
> +  VOID                                          *Buffer;
> +  UINTN                                         FileSize;
> +  BOOLEAN                                       IsSystemFmp;
> +  EFI_CAPSULE_HEADER                            *CapsuleHeader;
> +  EFI_STATUS                                    Status;
> +
> +  if (Argc != 3) {
> +    Print(L"CapsuleApp: Invalid Parameter.\n");
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  IsSystemFmp = FALSE;
> +  if (StrCmp(Argv[1], L"-DS") == 0) {
> +    IsSystemFmp = TRUE;
> +  }
> +
> +  CapsuleName = Argv[2];
> +  Status = ReadFileToBuffer(CapsuleName, &FileSize, &Buffer);
> +  if (EFI_ERROR(Status)) {
> +    Print(L"CapsuleApp: Capsule (%s) is not found.\n", CapsuleName);
> +    goto Done;
> +  }
> +
> +  CapsuleHeader = Buffer;
> +  if (CompareGuid(&CapsuleHeader->CapsuleGuid, &gWindowsUxCapsuleGuid)) {
> +    DumpUxCapsule(CapsuleHeader);
> +    Status = EFI_SUCCESS;
> +    goto Done;
> +  }
> +
> +  if (CompareGuid(&CapsuleHeader->CapsuleGuid, &gEfiFmpCapsuleGuid)) {
> +    DumpFmpCapsule(CapsuleHeader, IsSystemFmp);
> +  }
> +  if (IsNestedFmpCapsule(CapsuleHeader)) {
> +    Print(L"[NestedCapusule]\n");
> +    Print(L"CapsuleHeader:\n");
> +    Print(L"  CapsuleGuid      - %g\n", &CapsuleHeader->CapsuleGuid);
> +    Print(L"  HeaderSize       - 0x%x\n", CapsuleHeader->HeaderSize);
> +    Print(L"  Flags            - 0x%x\n", CapsuleHeader->Flags);
> +    Print(L"  CapsuleImageSize - 0x%x\n", CapsuleHeader->CapsuleImageSize);
> +    DumpFmpCapsule((EFI_CAPSULE_HEADER *)((UINTN)CapsuleHeader + CapsuleHeader-
> >HeaderSize), IsSystemFmp);
> +  }
> +
> +Done:
> +  FreePool(Buffer);
> +  return Status;
> +}
> +
> +/**
> +  Dump capsule status variable.
> +
> +  @retval EFI_SUCCESS            The capsule status variable is dumped.
> +  @retval EFI_UNSUPPORTED        Input parameter is not valid.
> +**/
> +EFI_STATUS
> +DmpCapsuleStatusVariable(
> +  VOID
> +  )
> +{
> +  EFI_STATUS                          Status;
> +  UINT32                              Index;
> +  CHAR16                              CapsuleVarName[20];
> +  CHAR16                              *TempVarName;
> +  EFI_CAPSULE_RESULT_VARIABLE_HEADER  *CapsuleResult;
> +  EFI_CAPSULE_RESULT_VARIABLE_FMP     *CapsuleResultFmp;
> +  UINTN                               CapsuleFileNameSize;
> +  CHAR16                              CapsuleIndexData[12];
> +  CHAR16                              *CapsuleIndex;
> +
> +  Status = GetVariable2(
> +             L"CapsuleMax",
> +             &gEfiCapsuleReportGuid,
> +             (VOID **)&CapsuleIndex,
> +             NULL
> +             );
> +  if (!EFI_ERROR(Status)) {
> +    CopyMem(CapsuleIndexData, CapsuleIndex, 11 * sizeof(CHAR16));
> +    CapsuleIndexData[11] = 0;
> +    Print(L"CapsuleMax - %s\n", CapsuleIndexData);
> +    FreePool(CapsuleIndex);
> +  }
> +  Status = GetVariable2(
> +             L"CapsuleLast",
> +             &gEfiCapsuleReportGuid,
> +             (VOID **)&CapsuleIndex,
> +             NULL
> +             );
> +  if (!EFI_ERROR(Status)) {
> +    CopyMem(CapsuleIndexData, CapsuleIndex, 11 * sizeof(CHAR16));
> +    CapsuleIndexData[11] = 0;
> +    Print(L"CapsuleLast - %s\n", CapsuleIndexData);
> +    FreePool(CapsuleIndex);
> +  }
> +
> +
> +  StrCpyS (CapsuleVarName, sizeof(CapsuleVarName)/sizeof(CapsuleVarName[0]),
> L"Capsule");
> +  TempVarName = CapsuleVarName + StrLen (CapsuleVarName);
> +  Index = 0;
> +
> +  while (TRUE) {
> +    UnicodeSPrint (TempVarName, 5 * sizeof(CHAR16), L"%04x", Index);
> +
> +    Status = GetVariable2 (
> +               CapsuleVarName,
> +               &gEfiCapsuleReportGuid,
> +               (VOID **) &CapsuleResult,
> +               NULL
> +               );
> +    if (Status == EFI_NOT_FOUND) {
> +      break;
> +    } else if (EFI_ERROR(Status)) {
> +      continue;
> +    }
> +
> +    //
> +    // display capsule process status
> +    //
> +    if (CapsuleResult->VariableTotalSize >=
> sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER)) {
> +      Print (L"CapsuleName: %s\n", CapsuleVarName);
> +      Print (L"  Capsule Guid: %g\n", &CapsuleResult->CapsuleGuid);
> +      Print (L"  Capsule ProcessedTime: %t\n", &CapsuleResult->CapsuleProcessed);
> +      Print (L"  Capsule Status: %r\n", CapsuleResult->CapsuleStatus);
> +    }
> +
> +    if (CompareGuid(&CapsuleResult->CapsuleGuid, &gEfiFmpCapsuleGuid)) {
> +      if (CapsuleResult->VariableTotalSize >=
> sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER) + sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP)) {
> +        CapsuleResultFmp = (EFI_CAPSULE_RESULT_VARIABLE_FMP *)(CapsuleResult + 1);
> +        Print(L"  Capsule FMP Version: 0x%x\n", CapsuleResultFmp->Version);
> +        Print(L"  Capsule FMP PayloadIndex: 0x%x\n", CapsuleResultFmp->PayloadIndex);
> +        Print(L"  Capsule FMP UpdateImageIndex: 0x%x\n", CapsuleResultFmp-
> >UpdateImageIndex);
> +        Print(L"  Capsule FMP UpdateImageTypeId: %g\n", &CapsuleResultFmp-
> >UpdateImageTypeId);
> +        if (CapsuleResult->VariableTotalSize >
> sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER) + sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP)) {
> +          Print(L"  Capsule FMP CapsuleFileName: %s\n", (CapsuleResultFmp + 1));
> +          CapsuleFileNameSize = StrSize((CHAR16 *)(CapsuleResultFmp + 1));
> +          if (CapsuleResult->VariableTotalSize >
> sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER) + sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP) +
> CapsuleFileNameSize) {
> +            Print(L"  Capsule FMP CapsuleTarget: %s\n", (UINT8 *)(CapsuleResultFmp +
> 1) + CapsuleFileNameSize);
> +          }
> +        }
> +      }
> +    }
> +
> +    FreePool(CapsuleResult);
> +
> +    Index++;
> +    if (Index > 0xFFFF) {
> +      break;
> +    }
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +CHAR8 *mFwTypeString[] = {
> +  "Unknown",
> +  "SystemFirmware",
> +  "DeviceFirmware",
> +  "UefiDriver",
> +};
> +
> +CHAR8 *mLastAttemptStatusString[] = {
> +  "Success",
> +  "Error: Unsuccessful",
> +  "Error: Insufficient Resources",
> +  "Error: Incorrect Version",
> +  "Error: Invalid Format",
> +  "Error: Auth Error",
> +  "Error: Power Event AC",
> +  "Error: Power Event Battery",
> +};
> +
> +/**
> +  Convert FwType to a string.
> +
> +  @param FwType  FwType in ESRT
> +
> +  @return a string for FwType.
> +**/
> +CHAR8 *
> +FwTypeToString(
> +  IN UINT32 FwType
> +  )
> +{
> +  if (FwType < sizeof(mFwTypeString) / sizeof(mFwTypeString[0])) {
> +    return mFwTypeString[FwType];
> +  } else {
> +    return "Invalid";
> +  }
> +}
> +
> +/**
> +  Convert LastAttemptStatus to a string.
> +
> +  @param LastAttemptStatus  LastAttemptStatus in FMP or ESRT
> +
> +  @return a string for LastAttemptStatus.
> +**/
> +CHAR8 *
> +LastAttemptStatusToString(
> +  IN UINT32 LastAttemptStatus
> +  )
> +{
> +  if (LastAttemptStatus < sizeof(mLastAttemptStatusString) /
> sizeof(mLastAttemptStatusString[0])) {
> +    return mLastAttemptStatusString[LastAttemptStatus];
> +  } else {
> +    return "Error: Unknown";
> +  }
> +}
> +
> +/**
> +  Dump ESRT entry.
> +
> +  @param EsrtEntry  ESRT entry
> +**/
> +VOID
> +DumpEsrtEntry(
> +  IN EFI_SYSTEM_RESOURCE_ENTRY  *EsrtEntry
> +  )
> +{
> +  Print(L"  FwClass                  - %g\n", &EsrtEntry->FwClass);
> +  Print(L"  FwType                   - 0x%x (%a)\n", EsrtEntry->FwType,
> FwTypeToString(EsrtEntry->FwType));
> +  Print(L"  FwVersion                - 0x%x\n", EsrtEntry->FwVersion);
> +  Print(L"  LowestSupportedFwVersion - 0x%x\n", EsrtEntry->LowestSupportedFwVersion);
> +  Print(L"  CapsuleFlags             - 0x%x\n", EsrtEntry->CapsuleFlags);
> +  Print(L"    PERSIST_ACROSS_RESET   - 0x%x\n", EsrtEntry->CapsuleFlags &
> CAPSULE_FLAGS_PERSIST_ACROSS_RESET);
> +  Print(L"    POPULATE_SYSTEM_TABLE  - 0x%x\n", EsrtEntry->CapsuleFlags &
> CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE);
> +  Print(L"    INITIATE_RESET         - 0x%x\n", EsrtEntry->CapsuleFlags &
> CAPSULE_FLAGS_INITIATE_RESET);
> +  Print(L"  LastAttemptVersion       - 0x%x\n", EsrtEntry->LastAttemptVersion);
> +  Print(L"  LastAttemptStatus        - 0x%x (%a)\n", EsrtEntry->LastAttemptStatus,
> LastAttemptStatusToString(EsrtEntry->LastAttemptStatus));
> +}
> +
> +/**
> +  Dump ESRT table.
> +
> +  @param Esrt  ESRT table
> +**/
> +VOID
> +DumpEsrt(
> +  IN EFI_SYSTEM_RESOURCE_TABLE  *Esrt
> +  )
> +{
> +  UINTN                      Index;
> +  EFI_SYSTEM_RESOURCE_ENTRY  *EsrtEntry;
> +
> +  Print(L"EFI_SYSTEM_RESOURCE_TABLE:\n");
> +  Print(L"FwResourceCount    - 0x%x\n", Esrt->FwResourceCount);
> +  Print(L"FwResourceCountMax - 0x%x\n", Esrt->FwResourceCountMax);
> +  Print(L"FwResourceVersion  - 0x%lx\n", Esrt->FwResourceVersion);
> +
> +  EsrtEntry = (VOID *)(Esrt + 1);
> +  for (Index = 0; Index < Esrt->FwResourceCount; Index++) {
> +    Print(L"EFI_SYSTEM_RESOURCE_ENTRY (%d):\n", Index);
> +    DumpEsrtEntry(EsrtEntry);
> +    EsrtEntry++;
> +  }
> +}
> +
> +/**
> +  Dump ESRT info.
> +**/
> +VOID
> +DumpEsrtData (
> +  VOID
> +  )
> +{
> +  EFI_STATUS                 Status;
> +  EFI_SYSTEM_RESOURCE_TABLE  *Esrt;
> +
> +  Print(L"##############\n");
> +  Print(L"# ESRT TABLE #\n");
> +  Print(L"##############\n");
> +
> +  Status = EfiGetSystemConfigurationTable (&gEfiSystemResourceTableGuid, (VOID
> **)&Esrt);
> +  if (EFI_ERROR(Status)) {
> +    Print(L"ESRT - %r\n", Status);
> +    return;
> +  }
> +  DumpEsrt(Esrt);
> +  Print(L"\n");
> +}
> +
> +/**
> +  Dump FMP information.
> +
> +  @param ImageInfoSize       The size of ImageInfo, in bytes.
> +  @param ImageInfo           A pointer to EFI_FIRMWARE_IMAGE_DESCRIPTOR.
> +  @param DescriptorVersion   The version of EFI_FIRMWARE_IMAGE_DESCRIPTOR.
> +  @param DescriptorCount     The count of EFI_FIRMWARE_IMAGE_DESCRIPTOR.
> +  @param DescriptorSize      The size of an individual EFI_FIRMWARE_IMAGE_DESCRIPTOR,
> in bytes.
> +  @param PackageVersion      The version of package.
> +  @param PackageVersionName  The version name of package.
> +**/
> +VOID
> +DumpFmpImageInfo(
> +  IN UINTN                           ImageInfoSize,
> +  IN EFI_FIRMWARE_IMAGE_DESCRIPTOR   *ImageInfo,
> +  IN UINT32                          DescriptorVersion,
> +  IN UINT8                           DescriptorCount,
> +  IN UINTN                           DescriptorSize,
> +  IN UINT32                          PackageVersion,
> +  IN CHAR16                          *PackageVersionName
> +  )
> +{
> +  EFI_FIRMWARE_IMAGE_DESCRIPTOR                 *CurrentImageInfo;
> +  UINTN                                         Index;
> +
> +  Print(L"  DescriptorVersion  - 0x%x\n", DescriptorVersion);
> +  Print(L"  DescriptorCount    - 0x%x\n", DescriptorCount);
> +  Print(L"  DescriptorSize     - 0x%x\n", DescriptorSize);
> +  Print(L"  PackageVersion     - 0x%x\n", PackageVersion);
> +  Print(L"  PackageVersionName - \"%s\"\n", PackageVersionName);
> +  CurrentImageInfo = ImageInfo;
> +  for (Index = 0; Index < DescriptorCount; Index++) {
> +    Print(L"  ImageDescriptor (%d)\n", Index);
> +    Print(L"    ImageIndex                  - 0x%x\n", CurrentImageInfo->ImageIndex);
> +    Print(L"    ImageTypeId                 - %g\n", &CurrentImageInfo->ImageTypeId);
> +    Print(L"    ImageId                     - 0x%lx\n", CurrentImageInfo->ImageId);
> +    Print(L"    ImageIdName                 - \"%s\"\n", CurrentImageInfo-
> >ImageIdName);
> +    Print(L"    Version                     - 0x%x\n", CurrentImageInfo->Version);
> +    Print(L"    VersionName                 - \"%s\"\n", CurrentImageInfo-
> >VersionName);
> +    Print(L"    Size                        - 0x%x\n", CurrentImageInfo->Size);
> +    Print(L"    AttributesSupported         - 0x%lx\n", CurrentImageInfo-
> >AttributesSupported);
> +    Print(L"      IMAGE_UPDATABLE           - 0x%lx\n", CurrentImageInfo-
> >AttributesSupported & IMAGE_ATTRIBUTE_IMAGE_UPDATABLE);
> +    Print(L"      RESET_REQUIRED            - 0x%lx\n", CurrentImageInfo-
> >AttributesSupported & IMAGE_ATTRIBUTE_RESET_REQUIRED);
> +    Print(L"      AUTHENTICATION_REQUIRED   - 0x%lx\n", CurrentImageInfo-
> >AttributesSupported & IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);
> +    Print(L"      IN_USE                    - 0x%lx\n", CurrentImageInfo-
> >AttributesSupported & IMAGE_ATTRIBUTE_IN_USE);
> +    Print(L"      UEFI_IMAGE                - 0x%lx\n", CurrentImageInfo-
> >AttributesSupported & IMAGE_ATTRIBUTE_UEFI_IMAGE);
> +    Print(L"    AttributesSetting           - 0x%lx\n", CurrentImageInfo-
> >AttributesSetting);
> +    Print(L"      IMAGE_UPDATABLE           - 0x%lx\n", CurrentImageInfo-
> >AttributesSetting & IMAGE_ATTRIBUTE_IMAGE_UPDATABLE);
> +    Print(L"      RESET_REQUIRED            - 0x%lx\n", CurrentImageInfo-
> >AttributesSetting & IMAGE_ATTRIBUTE_RESET_REQUIRED);
> +    Print(L"      AUTHENTICATION_REQUIRED   - 0x%lx\n", CurrentImageInfo-
> >AttributesSetting & IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);
> +    Print(L"      IN_USE                    - 0x%lx\n", CurrentImageInfo-
> >AttributesSetting & IMAGE_ATTRIBUTE_IN_USE);
> +    Print(L"      UEFI_IMAGE                - 0x%lx\n", CurrentImageInfo-
> >AttributesSetting & IMAGE_ATTRIBUTE_UEFI_IMAGE);
> +    Print(L"    Compatibilities             - 0x%lx\n", CurrentImageInfo-
> >Compatibilities);
> +    Print(L"      COMPATIB_CHECK_SUPPORTED  - 0x%lx\n", CurrentImageInfo-
> >Compatibilities & IMAGE_COMPATIBILITY_CHECK_SUPPORTED);
> +    if (DescriptorVersion > 1) {
> +      Print(L"    LowestSupportedImageVersion - 0x%x\n", CurrentImageInfo-
> >LowestSupportedImageVersion);
> +      if (DescriptorVersion > 2) {
> +        Print(L"    LastAttemptVersion          - 0x%x\n", CurrentImageInfo-
> >LastAttemptVersion);
> +        Print(L"    LastAttemptStatus           - 0x%x (%a)\n", CurrentImageInfo-
> >LastAttemptStatus, LastAttemptStatusToString(CurrentImageInfo->LastAttemptStatus));
> +        Print(L"    HardwareInstance            - 0x%lx\n", CurrentImageInfo-
> >HardwareInstance);
> +      }
> +    }
> +    //
> +    // Use DescriptorSize to move ImageInfo Pointer to stay compatible with different
> ImageInfo version
> +    //
> +    CurrentImageInfo = (EFI_FIRMWARE_IMAGE_DESCRIPTOR *)((UINT8 *)CurrentImageInfo +
> DescriptorSize);
> +  }
> +}
> +
> +/**
> +  Dump FMP package information.
> +
> +  @param PackageVersion             The version of package.
> +  @param PackageVersionName         The version name of package.
> +  @param PackageVersionNameMaxLen   The maximum length of PackageVersionName.
> +  @param AttributesSupported        Package attributes that are supported by this
> device.
> +  @param AttributesSetting          Package attributes.
> +**/
> +VOID
> +DumpFmpPackageInfo(
> +  IN UINT32                           PackageVersion,
> +  IN CHAR16                           *PackageVersionName,
> +  IN UINT32                           PackageVersionNameMaxLen,
> +  IN UINT64                           AttributesSupported,
> +  IN UINT64                           AttributesSetting
> +  )
> +{
> +  Print(L"  PackageVersion              - 0x%x\n", PackageVersion);
> +  Print(L"  PackageVersionName          - \"%s\"\n", PackageVersionName);
> +  Print(L"  PackageVersionNameMaxLen    - 0x%x\n", PackageVersionNameMaxLen);
> +  Print(L"  AttributesSupported         - 0x%lx\n", AttributesSupported);
> +  Print(L"    IMAGE_UPDATABLE           - 0x%lx\n", AttributesSupported &
> IMAGE_ATTRIBUTE_IMAGE_UPDATABLE);
> +  Print(L"    RESET_REQUIRED            - 0x%lx\n", AttributesSupported &
> IMAGE_ATTRIBUTE_RESET_REQUIRED);
> +  Print(L"    AUTHENTICATION_REQUIRED   - 0x%lx\n", AttributesSupported &
> IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);
> +  Print(L"  AttributesSetting           - 0x%lx\n", AttributesSetting);
> +  Print(L"    IMAGE_UPDATABLE           - 0x%lx\n", AttributesSetting &
> IMAGE_ATTRIBUTE_IMAGE_UPDATABLE);
> +  Print(L"    RESET_REQUIRED            - 0x%lx\n", AttributesSetting &
> IMAGE_ATTRIBUTE_RESET_REQUIRED);
> +  Print(L"    AUTHENTICATION_REQUIRED   - 0x%lx\n", AttributesSetting &
> IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);
> +}
> +
> +/**
> +  Dump FMP protocol info.
> +**/
> +VOID
> +DumpFmpData (
> +  VOID
> +  )
> +{
> +  EFI_STATUS                                    Status;
> +  EFI_FIRMWARE_MANAGEMENT_PROTOCOL              *Fmp;
> +  EFI_HANDLE                                    *HandleBuffer;
> +  UINTN                                         NumberOfHandles;
> +  UINTN                                         Index;
> +  EFI_FIRMWARE_IMAGE_DESCRIPTOR                 *FmpImageInfoBuf;
> +  UINTN                                         ImageInfoSize;
> +  UINT32                                        FmpImageInfoDescriptorVer;
> +  UINT8                                         FmpImageInfoCount;
> +  UINTN                                         DescriptorSize;
> +  UINT32                                        PackageVersion;
> +  CHAR16                                        *PackageVersionName;
> +  UINT32                                        PackageVersionNameMaxLen;
> +  UINT64                                        AttributesSupported;
> +  UINT64                                        AttributesSetting;
> +
> +  Print(L"############\n");
> +  Print(L"# FMP DATA #\n");
> +  Print(L"############\n");
> +  Status = gBS->LocateHandleBuffer (
> +                  ByProtocol,
> +                  &gEfiFirmwareManagementProtocolGuid,
> +                  NULL,
> +                  &NumberOfHandles,
> +                  &HandleBuffer
> +                  );
> +  if (EFI_ERROR(Status)) {
> +    Print(L"FMP protocol - %r\n", EFI_NOT_FOUND);
> +    return;
> +  }
> +
> +  for (Index = 0; Index < NumberOfHandles; Index++) {
> +    Status = gBS->HandleProtocol(
> +                    HandleBuffer[Index],
> +                    &gEfiFirmwareManagementProtocolGuid,
> +                    (VOID **)&Fmp
> +                    );
> +    if (EFI_ERROR(Status)) {
> +      continue;
> +    }
> +
> +    ImageInfoSize = 0;
> +    Status = Fmp->GetImageInfo (
> +                    Fmp,
> +                    &ImageInfoSize,
> +                    NULL,
> +                    NULL,
> +                    NULL,
> +                    NULL,
> +                    NULL,
> +                    NULL
> +                    );
> +    if (Status != EFI_BUFFER_TOO_SMALL) {
> +      continue;
> +    }
> +
> +    FmpImageInfoBuf = NULL;
> +    FmpImageInfoBuf = AllocateZeroPool (ImageInfoSize);
> +    if (FmpImageInfoBuf == NULL) {
> +      Status = EFI_OUT_OF_RESOURCES;
> +      goto EXIT;
> +    }
> +
> +    PackageVersionName = NULL;
> +    Status = Fmp->GetImageInfo (
> +                    Fmp,
> +                    &ImageInfoSize,               // ImageInfoSize
> +                    FmpImageInfoBuf,              // ImageInfo
> +                    &FmpImageInfoDescriptorVer,   // DescriptorVersion
> +                    &FmpImageInfoCount,           // DescriptorCount
> +                    &DescriptorSize,              // DescriptorSize
> +                    &PackageVersion,              // PackageVersion
> +                    &PackageVersionName           // PackageVersionName
> +                    );
> +
> +    //
> +    // If FMP GetInformation interface failed, skip this resource
> +    //
> +    if (EFI_ERROR(Status)) {
> +      Print(L"FMP (%d) ImageInfo - %r\n", Index, Status);
> +      FreePool(FmpImageInfoBuf);
> +      continue;
> +    }
> +
> +    Print(L"FMP (%d) ImageInfo:\n", Index);
> +    DumpFmpImageInfo(
> +      ImageInfoSize,               // ImageInfoSize
> +      FmpImageInfoBuf,             // ImageInfo
> +      FmpImageInfoDescriptorVer,   // DescriptorVersion
> +      FmpImageInfoCount,           // DescriptorCount
> +      DescriptorSize,              // DescriptorSize
> +      PackageVersion,              // PackageVersion
> +      PackageVersionName           // PackageVersionName
> +      );
> +
> +    if (PackageVersionName != NULL) {
> +      FreePool(PackageVersionName);
> +    }
> +    FreePool(FmpImageInfoBuf);
> +
> +    //
> +    // Get package info
> +    //
> +    PackageVersionName = NULL;
> +    Status = Fmp->GetPackageInfo (
> +                    Fmp,
> +                    &PackageVersion,              // PackageVersion
> +                    &PackageVersionName,          // PackageVersionName
> +                    &PackageVersionNameMaxLen,    // PackageVersionNameMaxLen
> +                    &AttributesSupported,         // AttributesSupported
> +                    &AttributesSetting            // AttributesSetting
> +                    );
> +    if (EFI_ERROR(Status)) {
> +      Print(L"FMP (%d) PackageInfo - %r\n", Index, Status);
> +    } else {
> +      Print(L"FMP (%d) ImageInfo:\n", Index);
> +      DumpFmpPackageInfo(
> +        PackageVersion,              // PackageVersion
> +        PackageVersionName,          // PackageVersionName
> +        PackageVersionNameMaxLen,    // PackageVersionNameMaxLen
> +        AttributesSupported,         // AttributesSupported
> +        AttributesSetting            // AttributesSetting
> +        );
> +
> +      if (PackageVersionName != NULL) {
> +        FreePool(PackageVersionName);
> +      }
> +    }
> +  }
> +  Print(L"\n");
> +
> +EXIT:
> +  FreePool(HandleBuffer);
> +}
> --
> 2.7.4.windows.1
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>
https://lists.01.org/mailman/listinfo/edk2-devel


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

* Re: [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application.
  2016-09-30 15:30             ` Carsey, Jaben
@ 2016-10-03 18:35               ` Rothman, Michael A
  2016-10-03 20:38                 ` Carsey, Jaben
  0 siblings, 1 reply; 83+ messages in thread
From: Rothman, Michael A @ 2016-10-03 18:35 UTC (permalink / raw)
  To: Carsey, Jaben, Ni, Ruiyu, Yao, Jiewen, Kinney, Michael D,
	edk2-devel@lists.01.org
  Cc: Tian, Feng, Zhang, Chao B, Gao, Liming, Zeng, Star,
	Rothman, Michael A

You mean update the LoadOptions reference to refer to the EFI_LOAD_OPTION structure? Because that’s in essence what it means.

Thanks,
Mike Rothman
(迈克 罗斯曼 / माइकल रोथ्मेन् / Михаил Ротман / משה רוטמן)
רועה עיקרי של חתולים

From: Carsey, Jaben
Sent: Friday, September 30, 2016 8:31 AM
To: Ni, Ruiyu <ruiyu.ni@intel.com>; Yao, Jiewen <jiewen.yao@intel.com>; Kinney, Michael D <michael.d.kinney@intel.com>; edk2-devel@lists.01.org; Rothman, Michael A <michael.a.rothman@intel.com>
Cc: Tian, Feng <feng.tian@intel.com>; Zhang, Chao B <chao.b.zhang@intel.com>; Gao, Liming <liming.gao@intel.com>; Zeng, Star <star.zeng@intel.com>; Carsey, Jaben <jaben.carsey@intel.com>
Subject: RE: [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application.

Mike Rothman,

Can we get LoadOptions and LoadOptionsSize clarified in the UEFI Spec?  This seems like a simple clarification and I would argue its needed.  The UEFI Shell is not the only producer of this protocol.  BDS launches things (like the UEFI Shell itself) and the shell already consumes it for itself (and it works).  I think it just needs clarification so people can depend on the current implementation not changing.

-Jaben

From: Ni, Ruiyu
Sent: Thursday, September 29, 2016 9:13 PM
To: Carsey, Jaben <jaben.carsey@intel.com<mailto:jaben.carsey@intel.com>>; Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>; edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>
Cc: Tian, Feng <feng.tian@intel.com<mailto:feng.tian@intel.com>>; Zhang, Chao B <chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com>>; Gao, Liming <liming.gao@intel.com<mailto:liming.gao@intel.com>>; Zeng, Star <star.zeng@intel.com<mailto:star.zeng@intel.com>>
Subject: RE: [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application.
Importance: High

Supposing user inputs “CapsuleApp.efi Parameter1 Parameter2”.
There is no spec to define what the LoadOption should equal to.
If there is another UEFI Shell implementation, it could interpret the command line then sets only “Parameter1 Parameter2” into LoadOption, or sets “CapsuleApp.efi\tParameter1\tParameter2” to LoadOption, or sets “[Shell]\tCapsuleApp.efi\tParameter1\tParameter2” to LoadOption.
Because it“produces” such LoadOption, it knows how to “consume”/parse it to get the ARGVs.

So I suggest we put the CapsuleApp in ShellPkg and let it use the ShellParameter protocol.

Regards,
Ray

From: Carsey, Jaben
Sent: Friday, September 30, 2016 3:11 AM
To: Ni, Ruiyu <ruiyu.ni@intel.com<mailto:ruiyu.ni@intel.com>>; Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>; edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>
Cc: Tian, Feng <feng.tian@intel.com<mailto:feng.tian@intel.com>>; Zhang, Chao B <chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com>>; Gao, Liming <liming.gao@intel.com<mailto:liming.gao@intel.com>>; Zeng, Star <star.zeng@intel.com<mailto:star.zeng@intel.com>>; Carsey, Jaben <jaben.carsey@intel.com<mailto:jaben.carsey@intel.com>>
Subject: RE: [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application.

I am confused.

Why is LoadOption and LoadOptionSize not working?  This is specified as part of UEFI Spec (Note: Not UEFI Shell Spec) as a standard way to pass parameters to UEFI appliations.  I think this should work (although it is more work than just examining argc/argv).

-Jaben

From: Ni, Ruiyu
Sent: Wednesday, September 28, 2016 11:40 PM
To: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>; edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>
Cc: Tian, Feng <feng.tian@intel.com<mailto:feng.tian@intel.com>>; Zhang, Chao B <chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com>>; Gao, Liming <liming.gao@intel.com<mailto:liming.gao@intel.com>>; Zeng, Star <star.zeng@intel.com<mailto:star.zeng@intel.com>>; Carsey, Jaben <jaben.carsey@intel.com<mailto:jaben.carsey@intel.com>>
Subject: RE: [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application.
Importance: High

Jiewen,
The way CapsuleApp extracts the ARGV assumes UEFI Shell encodes the parameters using a certain way. But the parameter encoding way is not described in the Shell spec.
Maybe we can put the CapsuleApp in ShellPkg, then let it directly use ShellParameter protocol to get the ARGV.

Copying Jaben.

Regards,
Ray

From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of Yao, Jiewen
Sent: Thursday, September 29, 2016 10:37 AM
To: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>; edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>
Cc: Tian, Feng <feng.tian@intel.com<mailto:feng.tian@intel.com>>; Zhang, Chao B <chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com>>; Gao, Liming <liming.gao@intel.com<mailto:liming.gao@intel.com>>; Zeng, Star <star.zeng@intel.com<mailto:star.zeng@intel.com>>
Subject: Re: [edk2] [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application.

Right. CapsuleOnDisk is not supported in BIOS yet.
I will remove it in CapsuleApp.

CapsuleApp just works as an agent to pass capsule to CapsuleDxeRuntime driver.
So it is checked by CapsuleDxeRuntime, not CapsuleApp.

Thank you
Yao Jiewen

From: Kinney, Michael D
Sent: Thursday, September 29, 2016 9:06 AM
To: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>; Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>
Cc: Tian, Feng <feng.tian@intel.com<mailto:feng.tian@intel.com>>; Zeng, Star <star.zeng@intel.com<mailto:star.zeng@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: [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application.

Jiewen,

Does the capsule on disk feature provided by this app work?

I tried it with the QuarkPlatformPkg capsule and I can get
The app to copy the capsule to an EFI System Partition, but
The logic after that point looks incomplete.

Also, if I clear the Persist and Reset flags on the capsule,
the immediate processing of the capsule does not work.

Is there any FW code that will look for capsules on disk?

If there are incomplete features in CapsuleApp, then I think
we should remove them.

Mike

> -----Original Message-----
> From: Yao, Jiewen
> Sent: Tuesday, September 20, 2016 11:45 PM
> To: edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org%3cmailto:edk2-devel@lists.01.org>>
> Cc: Tian, Feng <feng.tian@intel.com<mailto:feng.tian@intel.com<mailto:feng.tian@intel.com%3cmailto:feng.tian@intel.com>>>; Zeng, Star <star.zeng@intel.com<mailto:star.zeng@intel.com<mailto:star.zeng@intel.com%3cmailto:star.zeng@intel.com>>>; Kinney, Michael
> D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com%3cmailto:michael.d.kinney@intel.com>>>; Gao, Liming <liming.gao@intel.com<mailto:liming.gao@intel.com<mailto:liming.gao@intel.com%3cmailto:liming.gao@intel.com>>>; Zhang, Chao B
> <chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com%3cmailto:chao.b.zhang@intel.com>>>
> Subject: [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application.
>
> This CapsuleApp can help perform capsule update in UEFI shell environment.
> It can also dump capsule information, capsule status variable, ESRT and FMP.
>
> Cc: Feng Tian <feng.tian@intel.com<mailto:feng.tian@intel.com<mailto:feng.tian@intel.com%3cmailto:feng.tian@intel.com>>>
> Cc: Star Zeng <star.zeng@intel.com<mailto:star.zeng@intel.com<mailto:star.zeng@intel.com%3cmailto:star.zeng@intel.com>>>
> Cc: Michael D Kinney <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com%3cmailto:michael.d.kinney@intel.com>>>
> Cc: Liming Gao <liming.gao@intel.com<mailto:liming.gao@intel.com<mailto:liming.gao@intel.com%3cmailto:liming.gao@intel.com>>>
> Cc: Chao Zhang <chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com%3cmailto:chao.b.zhang@intel.com>>>
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Jiewen Yao <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com<mailto:jiewen.yao@intel.com%3cmailto:jiewen.yao@intel.com>>>
> ---
>  MdeModulePkg/Application/CapsuleApp/AppSupport.c        |  480 +++++++++
>  MdeModulePkg/Application/CapsuleApp/CapsuleApp.c        | 1047 ++++++++++++++++++++
>  MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf      |   71 ++
>  MdeModulePkg/Application/CapsuleApp/CapsuleApp.uni      |   22 +
>  MdeModulePkg/Application/CapsuleApp/CapsuleAppExtra.uni |   19 +
>  MdeModulePkg/Application/CapsuleApp/CapsuleDump.c       |  840 ++++++++++++++++
>  6 files changed, 2479 insertions(+)
>
> diff --git a/MdeModulePkg/Application/CapsuleApp/AppSupport.c
> b/MdeModulePkg/Application/CapsuleApp/AppSupport.c
> new file mode 100644
> index 0000000..365067d
> --- /dev/null
> +++ b/MdeModulePkg/Application/CapsuleApp/AppSupport.c
> @@ -0,0 +1,480 @@
> +/** @file
> +  A shell application that triggers capsule update process.
> +
> +  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the BSD License
> +  which accompanies this distribution.  The full text of the license may be found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +
> +**/
> +
> +#include <Uefi.h>
> +#include <Library/BaseLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/UefiRuntimeServicesTableLib.h>
> +#include <Library/UefiLib.h>
> +#include <Library/PrintLib.h>
> +#include <Protocol/LoadedImage.h>
> +#include <Protocol/SimpleFileSystem.h>
> +#include <Guid/FileInfo.h>
> +#include <Guid/Gpt.h>
> +
> +#define MAX_ARG_NUM     11
> +
> +UINTN  Argc = 0;
> +CHAR16 *Argv[MAX_ARG_NUM];
> +CHAR16 *ArgBuffer;
> +
> +/**
> +
> +  This function parse application ARG.
> +
> +  @return Status
> +**/
> +EFI_STATUS
> +GetArg (
> +  VOID
> +  )
> +{
> +  UINT8                         *Data;
> +  UINTN                         DataSize;
> +  CHAR16                        *Index;
> +  CHAR16                        *End;
> +  CHAR16                        *DIndex;
> +  EFI_STATUS                    Status;
> +  EFI_LOADED_IMAGE_PROTOCOL     *LoadedImage;
> +
> +  Status = gBS->HandleProtocol (
> +                  gImageHandle,
> +                  &gEfiLoadedImageProtocolGuid,
> +                  (VOID**)&LoadedImage
> +                  );
> +  if (EFI_ERROR(Status)) {
> +    return Status;
> +  }
> +
> +  Data = LoadedImage->LoadOptions;
> +  DataSize = LoadedImage->LoadOptionsSize;
> +
> +  End = (CHAR16*)(UINTN)(Data + DataSize);
> +  Status = gBS->AllocatePool (EfiBootServicesData, DataSize, (VOID **)&ArgBuffer);
> +  ASSERT_EFI_ERROR (Status);
> +  DIndex = ArgBuffer;
> +  Argv[Argc++] = ArgBuffer;
> +  for (Index = (CHAR16*)Data; Index < End; ) {
> +    if (*Index == L' ') {
> +      *DIndex = L'\0';
> +      if (Argc >= MAX_ARG_NUM) {
> +        return EFI_UNSUPPORTED;
> +      }
> +      Argv[Argc++] = (++ DIndex);
> +      while(*Index == L' ') {
> +        Index ++;
> +      }
> +    }
> +    (*(DIndex ++)) = (*(Index ++));
> +  }
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Clear APP ARG.
> +**/
> +VOID
> +CleanArg (
> +  VOID
> +  )
> +{
> +  FreePool (Argv[0]);
> +}
> +
> +/**
> +  Return File System Volume containing this shell application.
> +
> +  @return File System Volume containing this shell application.
> +**/
> +EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *
> +GetMyVol (
> +  VOID
> +  )
> +{
> +  EFI_STATUS                        Status;
> +  EFI_LOADED_IMAGE_PROTOCOL         *LoadedImage;
> +  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Vol;
> +
> +  Status = gBS->HandleProtocol (
> +                  gImageHandle,
> +                  &gEfiLoadedImageProtocolGuid,
> +                  (VOID **)&LoadedImage
> +                  );
> +  ASSERT_EFI_ERROR (Status);
> +
> +  Status = gBS->HandleProtocol (
> +                  LoadedImage->DeviceHandle,
> +                  &gEfiSimpleFileSystemProtocolGuid,
> +                  (VOID **)&Vol
> +                  );
> +  if (!EFI_ERROR (Status)) {
> +    return Vol;
> +  }
> +
> +  return NULL;
> +}
> +
> +/**
> +  Read a file from this volume.
> +
> +  @param Vol             File System Volume
> +  @param FileName        The file to be read.
> +  @param BufferSize      The file buffer size
> +  @param Buffer          The file buffer
> +
> +  @retval EFI_SUCCESS    Read file successfully
> +  @retval EFI_NOT_FOUND  File not found
> +**/
> +EFI_STATUS
> +ReadFileFromVol (
> +  IN  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Vol,
> +  IN  CHAR16                            *FileName,
> +  OUT UINTN                             *BufferSize,
> +  OUT VOID                              **Buffer
> +  )
> +{
> +  EFI_STATUS                        Status;
> +  EFI_FILE_HANDLE                   RootDir;
> +  EFI_FILE_HANDLE                   Handle;
> +  UINTN                             FileInfoSize;
> +  EFI_FILE_INFO                     *FileInfo;
> +  UINTN                             TempBufferSize;
> +  VOID                              *TempBuffer;
> +
> +  //
> +  // Open the root directory
> +  //
> +  Status = Vol->OpenVolume (Vol, &RootDir);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  //
> +  // Open the file
> +  //
> +  Status = RootDir->Open (
> +                      RootDir,
> +                      &Handle,
> +                      FileName,
> +                      EFI_FILE_MODE_READ,
> +                      0
> +                      );
> +  if (EFI_ERROR (Status)) {
> +    RootDir->Close (RootDir);
> +    return Status;
> +  }
> +
> +  RootDir->Close (RootDir);
> +
> +  //
> +  // Get the file information
> +  //
> +  FileInfoSize = sizeof(EFI_FILE_INFO) + 1024;
> +
> +  FileInfo = AllocateZeroPool (FileInfoSize);
> +  if (FileInfo == NULL) {
> +    Handle->Close (Handle);
> +    return Status;
> +  }
> +
> +  Status = Handle->GetInfo (
> +                     Handle,
> +                     &gEfiFileInfoGuid,
> +                     &FileInfoSize,
> +                     FileInfo
> +                     );
> +  if (EFI_ERROR (Status)) {
> +    Handle->Close (Handle);
> +    gBS->FreePool (FileInfo);
> +    return Status;
> +  }
> +
> +  //
> +  // Allocate buffer for the file data. The last CHAR16 is for L'\0'
> +  //
> +  TempBufferSize = (UINTN) FileInfo->FileSize + sizeof(CHAR16);
> +  TempBuffer = AllocateZeroPool (TempBufferSize);
> +  if (TempBuffer == NULL) {
> +    Handle->Close (Handle);
> +    gBS->FreePool (FileInfo);
> +    return Status;
> +  }
> +
> +  gBS->FreePool (FileInfo);
> +
> +  //
> +  // Read the file data to the buffer
> +  //
> +  Status = Handle->Read (
> +                     Handle,
> +                     &TempBufferSize,
> +                     TempBuffer
> +                     );
> +  if (EFI_ERROR (Status)) {
> +    Handle->Close (Handle);
> +    gBS->FreePool (TempBuffer);
> +    return Status;
> +  }
> +
> +  Handle->Close (Handle);
> +
> +  *BufferSize = TempBufferSize;
> +  *Buffer     = TempBuffer;
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Read a file.
> +  If ScanFs is FLASE, it will use this Vol as default Fs.
> +  If ScanFs is TRUE, it will scan all FS and check the file.
> +    If there is only one file match the name, it will be read.
> +    If there is more than one file match the name, it will return Error.
> +
> +  @param ThisVol         File System Volume
> +  @param FileName        The file to be read.
> +  @param BufferSize      The file buffer size
> +  @param Buffer          The file buffer
> +  @param ScanFs          Need Scan all FS
> +
> +  @retval EFI_SUCCESS    Read file successfully
> +  @retval EFI_NOT_FOUND  File not found
> +  @retval EFI_NO_MAPPING There is duplicated files found
> +**/
> +EFI_STATUS
> +ReadFileToBufferEx (
> +  IN OUT EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   **ThisVol,
> +  IN  CHAR16                               *FileName,
> +  OUT UINTN                                *BufferSize,
> +  OUT VOID                                 **Buffer,
> +  IN  BOOLEAN                              ScanFs
> +  )
> +{
> +  EFI_STATUS                        Status;
> +  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Vol;
> +  UINTN                             TempBufferSize;
> +  VOID                              *TempBuffer;
> +  UINTN                             NoHandles;
> +  EFI_HANDLE                        *HandleBuffer;
> +  UINTN                             Index;
> +
> +  //
> +  // Check parameters
> +  //
> +  if ((FileName == NULL) || (Buffer == NULL) || (ThisVol == NULL)) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  //
> +  // not scan fs
> +  //
> +  if (!ScanFs) {
> +    if (*ThisVol == NULL) {
> +      *ThisVol = GetMyVol ();
> +      if (*ThisVol == NULL) {
> +        return EFI_INVALID_PARAMETER;
> +      }
> +    }
> +    //
> +    // Read file directly from Vol
> +    //
> +    return ReadFileFromVol (*ThisVol, FileName, BufferSize, Buffer);
> +  }
> +
> +  //
> +  // need scan fs
> +  //
> +
> +  //
> +  // Get all Vol handle
> +  //
> +  Status = gBS->LocateHandleBuffer (
> +                   ByProtocol,
> +                   &gEfiSimpleFileSystemProtocolGuid,
> +                   NULL,
> +                   &NoHandles,
> +                   &HandleBuffer
> +                   );
> +  if (EFI_ERROR (Status) && (NoHandles == 0)) {
> +    return EFI_NOT_FOUND;
> +  }
> +
> +  //
> +  // Walk through each Vol
> +  //
> +  *ThisVol = NULL;
> +  *BufferSize = 0;
> +  *Buffer     = NULL;
> +  for (Index = 0; Index < NoHandles; Index++) {
> +    Status = gBS->HandleProtocol (
> +                    HandleBuffer[Index],
> +                    &gEfiSimpleFileSystemProtocolGuid,
> +                    (VOID **)&Vol
> +                    );
> +    if (EFI_ERROR(Status)) {
> +      continue;
> +    }
> +
> +    Status = ReadFileFromVol (Vol, FileName, &TempBufferSize, &TempBuffer);
> +    if (!EFI_ERROR (Status)) {
> +      //
> +      // Read file OK, check duplication
> +      //
> +      if (*ThisVol != NULL) {
> +        //
> +        // Find the duplicated file
> +        //
> +        gBS->FreePool (TempBuffer);
> +        gBS->FreePool (*Buffer);
> +        Print (L"Duplicated FileName found!\n");
> +        return EFI_NO_MAPPING;
> +      } else {
> +        //
> +        // Record value
> +        //
> +        *ThisVol = Vol;
> +        *BufferSize = TempBufferSize;
> +        *Buffer     = TempBuffer;
> +      }
> +    }
> +  }
> +
> +  //
> +  // Scan Fs done
> +  //
> +  if (*ThisVol == NULL) {
> +    return EFI_NOT_FOUND;
> +  }
> +
> +  //
> +  // Done
> +  //
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Read a file.
> +
> +  @param FileName        The file to be read.
> +  @param BufferSize      The file buffer size
> +  @param Buffer          The file buffer
> +
> +  @retval EFI_SUCCESS    Read file successfully
> +  @retval EFI_NOT_FOUND  File not found
> +**/
> +EFI_STATUS
> +ReadFileToBuffer (
> +  IN  CHAR16                               *FileName,
> +  OUT UINTN                                *BufferSize,
> +  OUT VOID                                 **Buffer
> +  )
> +{
> +  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Vol;
> +  Vol = NULL;
> +  return ReadFileToBufferEx(&Vol, FileName, BufferSize, Buffer, FALSE);
> +}
> +
> +/**
> +  Write a file.
> +
> +  @param FileName        The file to be written.
> +  @param BufferSize      The file buffer size
> +  @param Buffer          The file buffer
> +
> +  @retval EFI_SUCCESS    Write file successfully
> +**/
> +EFI_STATUS
> +WriteFileFromBuffer(
> +  IN  CHAR16                               *FileName,
> +  IN  UINTN                                BufferSize,
> +  IN  VOID                                 *Buffer
> +  )
> +{
> +  EFI_STATUS                        Status;
> +  EFI_FILE_HANDLE                   RootDir;
> +  EFI_FILE_HANDLE                   Handle;
> +  UINTN                             TempBufferSize;
> +  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Vol;
> +
> +  Vol = GetMyVol();
> +
> +  //
> +  // Open the root directory
> +  //
> +  Status = Vol->OpenVolume (Vol, &RootDir);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  //
> +  // Open the file
> +  //
> +  Status = RootDir->Open (
> +                      RootDir,
> +                      &Handle,
> +                      FileName,
> +                      EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE| EFI_FILE_MODE_CREATE,
> +                      0
> +                      );
> +  if (EFI_ERROR (Status)) {
> +    RootDir->Close (RootDir);
> +    return Status;
> +  }
> +
> +  //
> +  // Delete file
> +  //
> +  Status = Handle->Delete(Handle);
> +  if (EFI_ERROR(Status)) {
> +    return Status;
> +  }
> +
> +  //
> +  // Open the file again
> +  //
> +  Status = RootDir->Open (
> +                      RootDir,
> +                      &Handle,
> +                      FileName,
> +                      EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE| EFI_FILE_MODE_CREATE,
> +                      0
> +                      );
> +  if (EFI_ERROR (Status)) {
> +    RootDir->Close (RootDir);
> +    return Status;
> +  }
> +
> +  RootDir->Close (RootDir);
> +
> +  //
> +  // Write the file data from the buffer
> +  //
> +  TempBufferSize = BufferSize;
> +  Status = Handle->Write (
> +                     Handle,
> +                     &TempBufferSize,
> +                     Buffer
> +                     );
> +  if (EFI_ERROR (Status)) {
> +    Handle->Close (Handle);
> +    return Status;
> +  }
> +
> +  Handle->Close (Handle);
> +
> +  return EFI_SUCCESS;
> +}
> +
> diff --git a/MdeModulePkg/Application/CapsuleApp/CapsuleApp.c
> b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.c
> new file mode 100644
> index 0000000..0a28557
> --- /dev/null
> +++ b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.c
> @@ -0,0 +1,1047 @@
> +/** @file
> +  A shell application that triggers capsule update process.
> +
> +  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the BSD License
> +  which accompanies this distribution.  The full text of the license may be found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +
> +**/
> +
> +#include <Uefi.h>
> +#include <Library/BaseLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/UefiRuntimeServicesTableLib.h>
> +#include <Library/UefiLib.h>
> +#include <Library/PrintLib.h>
> +#include <Protocol/LoadedImage.h>
> +#include <Protocol/SimpleFileSystem.h>
> +#include <Protocol/GraphicsOutput.h>
> +#include <Guid/FileInfo.h>
> +#include <Guid/Gpt.h>
> +#include <Guid/GlobalVariable.h>
> +#include <Guid/CapsuleReport.h>
> +#include <Guid/SystemResourceTable.h>
> +#include <Guid/FmpCapsule.h>
> +#include <IndustryStandard/WindowsUxCapsule.h>
> +
> +#define CAPSULE_HEADER_SIZE  0x20
> +
> +#define NESTED_CAPSULE_HEADER_SIZE  SIZE_4KB
> +#define SYSTEM_FIRMWARE_FLAG 0x50000
> +#define DEVICE_FIRMWARE_FLAG 0x78010
> +
> +#define EFI_CAPSULE_FROM_FILE_DIR                           L"\\EFI\\UpdateCapsule\\<file:///\\EFI\UpdateCapsule\><file:///\\EFI\UpdateCapsule\%3cfile:\EFI\UpdateCapsule\%3e>"
> +#define EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED  0x0000000000000004
> +
> +#define MAJOR_VERSION   1
> +#define MINOR_VERSION   0
> +
> +#define MAX_ARG_NUM     11
> +#define MAX_CAPSULE_NUM (MAX_ARG_NUM - 1)
> +
> +extern UINTN  Argc;
> +extern CHAR16 *Argv[];
> +
> +//
> +// Define how many block descriptors we want to test with.
> +//
> +UINTN  NumberOfDescriptors = 1;
> +UINTN  CapsuleFirstIndex;
> +UINTN  CapsuleLastIndex;
> +
> +/**
> +  Dump capsule information
> +
> +  @retval EFI_SUCCESS            The capsule information is dumped.
> +  @retval EFI_UNSUPPORTED        Input parameter is not valid.
> +**/
> +EFI_STATUS
> +DumpCapsule(
> +  VOID
> +  );
> +
> +/**
> +  Dump capsule status variable.
> +
> +  @retval EFI_SUCCESS            The capsule status variable is dumped.
> +  @retval EFI_UNSUPPORTED        Input parameter is not valid.
> +**/
> +EFI_STATUS
> +DmpCapsuleStatusVariable(
> +  VOID
> +  );
> +
> +/**
> +  Dump FMP protocol info.
> +**/
> +VOID
> +DumpFmpData(
> +  VOID
> +  );
> +
> +/**
> +  Dump ESRT info.
> +**/
> +VOID
> +DumpEsrtData(
> +  VOID
> +  );
> +
> +/**
> +  Read a file.
> +
> +  @param FileName        The file to be read.
> +  @param BufferSize      The file buffer size
> +  @param Buffer          The file buffer
> +
> +  @retval EFI_SUCCESS    Read file successfully
> +  @retval EFI_NOT_FOUND  File not found
> +**/
> +EFI_STATUS
> +ReadFileToBuffer(
> +  IN  CHAR16                               *FileName,
> +  OUT UINTN                                *BufferSize,
> +  OUT VOID                                 **Buffer
> +  );
> +
> +/**
> +  Write a file.
> +
> +  @param FileName        The file to be written.
> +  @param BufferSize      The file buffer size
> +  @param Buffer          The file buffer
> +
> +  @retval EFI_SUCCESS    Write file successfully
> +**/
> +EFI_STATUS
> +WriteFileFromBuffer(
> +  IN  CHAR16                               *FileName,
> +  IN  UINTN                                BufferSize,
> +  IN  VOID                                 *Buffer
> +  );
> +
> +/**
> +
> +  This function parse application ARG.
> +
> +  @return Status
> +**/
> +EFI_STATUS
> +GetArg (
> +  VOID
> +  );
> +
> +/**
> +  Clear APP ARG.
> +**/
> +VOID
> +CleanArg (
> +  VOID
> +  );
> +
> +/**
> +  Create UX capsule.
> +
> +  @retval EFI_SUCCESS            The capsule header is appended.
> +  @retval EFI_UNSUPPORTED        Input parameter is not valid.
> +  @retval EFI_OUT_OF_RESOURCES   No enough resource to create UX capsule.
> +**/
> +EFI_STATUS
> +CreateBmpFmp(
> +  VOID
> +  )
> +{
> +  CHAR16                                        *OutputCapsuleName;
> +  VOID                                          *BmpBuffer;
> +  UINTN                                         FileSize;
> +  CHAR16                                        *BmpName;
> +  UINT8                                         *FullCapsuleBuffer;
> +  UINTN                                         FullCapsuleBufferSize;
> +  EFI_DISPLAY_CAPSULE                           *DisplayCapsule;
> +  EFI_STATUS                                    Status;
> +  EFI_GRAPHICS_OUTPUT_PROTOCOL                  *Gop;
> +
> +  Status = gBS->LocateProtocol(&gEfiGraphicsOutputProtocolGuid, NULL, (VOID **)&Gop);
> +  if (EFI_ERROR(Status)) {
> +    Print(L"CapsuleApp: NO GOP is found.\n");
> +    return EFI_UNSUPPORTED;
> +  }
> +  Print(L"Current GOP: Mode - %d, ", Gop->Mode->Mode);
> +  Print(L"HorizontalResolution - %d, ", Gop->Mode->Info->HorizontalResolution);
> +  Print(L"VerticalResolution - %d\n", Gop->Mode->Info->VerticalResolution);
> +  // HorizontalResolution >= BMP_IMAGE_HEADER.PixelWidth
> +  // VerticalResolution   >= BMP_IMAGE_HEADER.PixelHeight
> +
> +  if (Argc != 5) {
> +    Print(L"CapsuleApp: Invalid Parameter.\n");
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  if (StrCmp(Argv[3], L"-O") != 0) {
> +    Print(L"CapsuleApp: NO output capsule name.\n");
> +    return EFI_UNSUPPORTED;
> +  }
> +  OutputCapsuleName = Argv[4];
> +
> +  BmpBuffer = NULL;
> +  FileSize = 0;
> +  FullCapsuleBuffer = NULL;
> +
> +  BmpName = Argv[2];
> +  Status = ReadFileToBuffer(BmpName, &FileSize, &BmpBuffer);
> +  if (EFI_ERROR(Status)) {
> +    Print(L"CapsuleApp: BMP image (%s) is not found.\n", BmpName);
> +    goto Done;
> +  }
> +
> +  FullCapsuleBufferSize = sizeof(EFI_DISPLAY_CAPSULE) + FileSize;
> +  FullCapsuleBuffer = AllocatePool(FullCapsuleBufferSize);
> +  if (FullCapsuleBuffer == NULL) {
> +    Print(L"CapsuleApp: Capsule Buffer size (0x%x) too big.\n",
> FullCapsuleBufferSize);
> +    Status = EFI_OUT_OF_RESOURCES;
> +    goto Done;
> +  }
> +
> +  DisplayCapsule = (EFI_DISPLAY_CAPSULE *)FullCapsuleBuffer;
> +  CopyGuid(&DisplayCapsule->CapsuleHeader.CapsuleGuid, &gWindowsUxCapsuleGuid);
> +  DisplayCapsule->CapsuleHeader.HeaderSize = sizeof(DisplayCapsule->CapsuleHeader);
> +  DisplayCapsule->CapsuleHeader.Flags = CAPSULE_FLAGS_PERSIST_ACROSS_RESET;
> +  DisplayCapsule->CapsuleHeader.CapsuleImageSize = (UINT32)FullCapsuleBufferSize;
> +
> +  DisplayCapsule->ImagePayload.Version = 1;
> +  DisplayCapsule->ImagePayload.Checksum = 0;
> +  DisplayCapsule->ImagePayload.ImageType = 0; // BMP
> +  DisplayCapsule->ImagePayload.Reserved = 0;
> +  DisplayCapsule->ImagePayload.Mode = Gop->Mode->Mode;
> +  DisplayCapsule->ImagePayload.OffsetX = 0;
> +  DisplayCapsule->ImagePayload.OffsetY = 0;
> +
> +  CopyMem((DisplayCapsule + 1), BmpBuffer, FileSize);
> +
> +  DisplayCapsule->ImagePayload.Checksum = CalculateCheckSum8(FullCapsuleBuffer,
> FullCapsuleBufferSize);
> +
> +  Status = WriteFileFromBuffer(OutputCapsuleName, FullCapsuleBufferSize,
> FullCapsuleBuffer);
> +  Print(L"CapsuleApp: Write %s %r\n", OutputCapsuleName, Status);
> +
> +Done:
> +  if (BmpBuffer != NULL) {
> +    FreePool(BmpBuffer);
> +  }
> +
> +  if (FullCapsuleBuffer != NULL) {
> +    FreePool(FullCapsuleBuffer);
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  Get ImageTypeId in the FMP capsule header.
> +
> +  @param CapsuleHeader  The FMP capsule image header.
> +
> +  @return ImageTypeId
> +**/
> +EFI_GUID *
> +GetCapsuleImageTypeId(
> +  IN EFI_CAPSULE_HEADER                            *CapsuleHeader
> +  )
> +{
> +  EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER       *FmpCapsuleHeader;
> +  UINT64                                       *ItemOffsetList;
> +  EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader;
> +
> +  FmpCapsuleHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *)((UINT8 *)CapsuleHeader
> + CapsuleHeader->HeaderSize);
> +  ItemOffsetList = (UINT64 *)(FmpCapsuleHeader + 1);
> +  if (FmpCapsuleHeader->PayloadItemCount == 0) {
> +    return NULL;
> +  }
> +  ImageHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *)((UINT8
> *)FmpCapsuleHeader + ItemOffsetList[FmpCapsuleHeader->EmbeddedDriverCount]);
> +  return &ImageHeader->UpdateImageTypeId;
> +}
> +
> +/**
> +  Get ESRT FwType according to ImageTypeId
> +
> +  @param  ImageTypeId   ImageTypeId of an FMP capsule.
> +
> +  @return ESRT FwType
> +**/
> +UINT32
> +GetEsrtFwType(
> +  IN  EFI_GUID                                      *ImageTypeId
> +  )
> +{
> +  EFI_STATUS                 Status;
> +  EFI_SYSTEM_RESOURCE_TABLE  *Esrt;
> +  EFI_SYSTEM_RESOURCE_ENTRY  *EsrtEntry;
> +  UINTN                      Index;
> +
> +  //
> +  // Check ESRT
> +  //
> +  Status = EfiGetSystemConfigurationTable(&gEfiSystemResourceTableGuid, (VOID
> **)&Esrt);
> +  if (!EFI_ERROR(Status)) {
> +    EsrtEntry = (VOID *)(Esrt + 1);
> +    for (Index = 0; Index < Esrt->FwResourceCount; Index++, EsrtEntry++) {
> +      if (CompareGuid(&EsrtEntry->FwClass, ImageTypeId)) {
> +        return EsrtEntry->FwType;
> +      }
> +    }
> +  }
> +
> +  return ESRT_FW_TYPE_UNKNOWN;
> +}
> +
> +/**
> +  Append a capsule header on top of current image.
> +  This function follows Windows UEFI Firmware Update Platform document.
> +
> +  @retval EFI_SUCCESS            The capsule header is appended.
> +  @retval EFI_UNSUPPORTED        Input parameter is not valid.
> +  @retval EFI_OUT_OF_RESOURCES   No enough resource to append capsule header.
> +**/
> +EFI_STATUS
> +CreateNestedFmp(
> +  VOID
> +  )
> +{
> +  CHAR16                                        *OutputCapsuleName;
> +  VOID                                          *CapsuleBuffer;
> +  UINTN                                         FileSize;
> +  CHAR16                                        *CapsuleName;
> +  UINT8                                         *FullCapsuleBuffer;
> +  UINTN                                         FullCapsuleBufferSize;
> +  EFI_CAPSULE_HEADER                            *NestedCapsuleHeader;
> +  EFI_GUID                                      *ImageTypeId;
> +  UINT32                                        FwType;
> +  EFI_STATUS                                    Status;
> +
> +  if (Argc != 5) {
> +    Print(L"CapsuleApp: Invalid Parameter.\n");
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  if (StrCmp(Argv[3], L"-O") != 0) {
> +    Print(L"CapsuleApp: NO output capsule name.\n");
> +    return EFI_UNSUPPORTED;
> +  }
> +  OutputCapsuleName = Argv[4];
> +
> +  CapsuleBuffer = NULL;
> +  FileSize = 0;
> +  FullCapsuleBuffer = NULL;
> +
> +  CapsuleName = Argv[2];
> +  Status = ReadFileToBuffer(CapsuleName, &FileSize, &CapsuleBuffer);
> +  if (EFI_ERROR(Status)) {
> +    Print(L"CapsuleApp: Capsule image (%s) is not found.\n", CapsuleName);
> +    goto Done;
> +  }
> +
> +  ImageTypeId = GetCapsuleImageTypeId(CapsuleBuffer);
> +  if (ImageTypeId == NULL) {
> +    Print(L"CapsuleApp: Capsule ImageTypeId is not found.\n");
> +    goto Done;
> +  }
> +  FwType = GetEsrtFwType(ImageTypeId);
> +  if ((FwType != ESRT_FW_TYPE_SYSTEMFIRMWARE) && (FwType !=
> ESRT_FW_TYPE_DEVICEFIRMWARE)) {
> +    Print(L"CapsuleApp: Capsule FwType is invalid.\n");
> +    goto Done;
> +  }
> +
> +  FullCapsuleBufferSize = NESTED_CAPSULE_HEADER_SIZE + FileSize;
> +  FullCapsuleBuffer = AllocatePool(FullCapsuleBufferSize);
> +  if (FullCapsuleBuffer == NULL) {
> +    Print(L"CapsuleApp: Capsule Buffer size (0x%x) too big.\n",
> FullCapsuleBufferSize);
> +    Status = EFI_OUT_OF_RESOURCES;
> +    goto Done;
> +  }
> +
> +  NestedCapsuleHeader = (EFI_CAPSULE_HEADER *)FullCapsuleBuffer;
> +  ZeroMem(NestedCapsuleHeader, NESTED_CAPSULE_HEADER_SIZE);
> +  CopyGuid(&NestedCapsuleHeader->CapsuleGuid, ImageTypeId);
> +  NestedCapsuleHeader->HeaderSize = NESTED_CAPSULE_HEADER_SIZE;
> +  NestedCapsuleHeader->Flags = (FwType == ESRT_FW_TYPE_DEVICEFIRMWARE) ?
> SYSTEM_FIRMWARE_FLAG : DEVICE_FIRMWARE_FLAG;
> +  NestedCapsuleHeader->CapsuleImageSize = (UINT32)FullCapsuleBufferSize;
> +
> +  CopyMem((UINT8 *)NestedCapsuleHeader + NestedCapsuleHeader->HeaderSize,
> CapsuleBuffer, FileSize);
> +
> +  Status = WriteFileFromBuffer(OutputCapsuleName, FullCapsuleBufferSize,
> FullCapsuleBuffer);
> +  Print(L"CapsuleApp: Write %s %r\n", OutputCapsuleName, Status);
> +
> +Done:
> +  if (CapsuleBuffer != NULL) {
> +    FreePool(CapsuleBuffer);
> +  }
> +
> +  if (FullCapsuleBuffer != NULL) {
> +    FreePool(FullCapsuleBuffer);
> +  }
> +
> +  return Status;
> +}
> +
> +
> +/**
> +  Clear capsule status variable.
> +
> +  @retval EFI_SUCCESS            The capsule status variable is cleared.
> +**/
> +EFI_STATUS
> +ClearCapsuleStatusVariable(
> +  VOID
> +  )
> +{
> +  EFI_STATUS                          Status;
> +  UINT32                              Index;
> +  CHAR16                              CapsuleVarName[20];
> +  CHAR16                              *TempVarName;
> +
> +  StrCpyS (CapsuleVarName, sizeof(CapsuleVarName)/sizeof(CapsuleVarName[0]),
> L"Capsule");
> +  TempVarName = CapsuleVarName + StrLen (CapsuleVarName);
> +  Index = 0;
> +
> +  while (TRUE) {
> +    UnicodeSPrint (TempVarName, 5 * sizeof(CHAR16), L"%04x", Index);
> +
> +    Status = gRT->SetVariable (
> +                    CapsuleVarName,
> +                    &gEfiCapsuleReportGuid,
> +                    EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS |
> EFI_VARIABLE_BOOTSERVICE_ACCESS,
> +                    0,
> +                    (VOID *)NULL
> +                    );
> +    if (EFI_ERROR(Status)) {
> +      //
> +      // There is no capsule variables, quit
> +      //
> +      break;
> +    }
> +
> +    Index++;
> +    if (Index > 0xFFFF) {
> +      break;
> +    }
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Get the active UEFI system partition from bootoption list.
> +
> +  @param[out] Fs    Simple File System protocol on the active UEFI system partition
> +
> +  @retval EFI_SUCCESS   active UEFI system partition found
> +**/
> +EFI_STATUS
> +GetEfiSysPartition(
> +  OUT EFI_SIMPLE_FILE_SYSTEM_PROTOCOL **Fs
> +  )
> +{
> +  EFI_STATUS                       Status;
> +  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL  *FsTemp;
> +  UINTN                            NoHandles;
> +  EFI_HANDLE                       *Handles;
> +  UINTN                            Index;
> +
> +  Handles = NULL;
> +
> +  //
> +  // search for EFI system partition protocol on Boot option device path
> +  //
> +  Status = gBS->LocateHandleBuffer(ByProtocol, &gEfiPartTypeSystemPartGuid, NULL,
> &NoHandles, &Handles);
> +  if (EFI_ERROR(Status)) {
> +    return Status;
> +  }
> +
> +  //
> +  // Skip BootOptions within FV
> +  //
> +  for (Index = 0; Index < NoHandles; Index++) {
> +    Status = gBS->HandleProtocol (Handles[Index], &gEfiSimpleFileSystemProtocolGuid,
> (VOID **)&FsTemp);
> +    if (!EFI_ERROR (Status)){
> +      *Fs = FsTemp;
> +      break;
> +    }
> +  }
> +  return Status;
> +}
> +
> +/**
> +  Copy a list of capsule images to the active UEFI system partition from bootoption
> list.
> +
> +  @param[in] CapsuleBuffer    An array of pointer to capsule images
> +  @param[in] FileSize         An array of UINTN to capsule images size
> +  @param[in] CapsuleNum       The count of capsule images
> +
> +  @retval EFI_SUCCESS   Capsule images are copied to the active UEFI system partition
> +**/
> +EFI_STATUS
> +CopyCapsuleToActiveEfiPartition(
> +  IN VOID                          **CapsuleBuffer,
> +  IN UINTN                         *FileSize,
> +  IN UINTN                         CapsuleNum
> +  )
> +{
> +  EFI_STATUS                       Status;
> +  CHAR16                           *CapsuleName;
> +  UINTN                            Index;
> +  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL  *Fs;
> +  EFI_FILE_HANDLE                  RootDir;
> +  EFI_FILE_HANDLE                  CapsuleDir;
> +  EFI_FILE_HANDLE                  DestHandle;
> +  UINTN                            DataSize;
> +  UINT64                           OsIndication;
> +
> +  RootDir      = NULL;
> +  CapsuleDir   = NULL;
> +
> +  Status = GetEfiSysPartition(&Fs);
> +  if (EFI_ERROR(Status)) {
> +    Print (L"Can not find active UEFI System Partition\n");
> +    return Status;
> +  }
> +
> +  Status = Fs->OpenVolume(Fs, &RootDir);
> +  if (EFI_ERROR(Status)) {
> +    goto EXIT;
> +  }
> +
> +  Status = RootDir->Open(
> +                      RootDir,
> +                      &CapsuleDir,
> +                      EFI_CAPSULE_FROM_FILE_DIR,
> +                      EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE,
> +                      EFI_FILE_DIRECTORY
> +                      );
> +  if (EFI_ERROR(Status)) {
> +    goto EXIT;
> +  }
> +
> +  //
> +  // Read the input files.
> +  //
> +  for (Index = 0; Index < CapsuleNum; Index++) {
> +    CapsuleName = Argv[CapsuleFirstIndex + Index];
> +    Status = CapsuleDir->Open(
> +                           CapsuleDir,
> +                           &DestHandle,
> +                           CapsuleName,
> +                           EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE |
> EFI_FILE_MODE_CREATE,
> +                           EFI_FILE_ARCHIVE
> +                           );
> +    if (EFI_ERROR(Status)) {
> +      Print(L"CapsuleApp: %s open error - %r\n", CapsuleName, Status);
> +      continue;
> +    }
> +
> +    DataSize = FileSize[Index];
> +    Status = DestHandle->Write(
> +                           DestHandle,
> +                           &DataSize,
> +                           CapsuleBuffer[Index]
> +                           );
> +    DestHandle->Close(DestHandle);
> +    if (EFI_ERROR(Status)) {
> +      Print(L"CapsuleApp: %s write error - %r, FileSize - 0x%x\n", CapsuleName,
> Status, FileSize[Index]);
> +    }
> +  }
> +
> +  Status = gRT->GetVariable (
> +                  L"OsIndications",
> +                  &gEfiGlobalVariableGuid,
> +                  NULL,
> +                  &DataSize,
> +                  (VOID *) &OsIndication
> +                  );
> +
> +  if (EFI_ERROR(Status) || DataSize != sizeof(OsIndication)) {
> +    OsIndication = 0;
> +  }
> +
> +  //
> +  // Set OsIndications Variable EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED bit
> +  //
> +  OsIndication |= EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED;
> +  Status = gRT->SetVariable (
> +                  L"OsIndications",
> +                  &gEfiGlobalVariableGuid,
> +                  EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS |
> +                  EFI_VARIABLE_BOOTSERVICE_ACCESS,
> +                  sizeof(OsIndication),
> +                  (VOID *)&OsIndication
> +                  );
> +
> +
> +EXIT:
> +  if (RootDir != NULL) {
> +    RootDir->Close(RootDir);
> +  }
> +
> +  if (CapsuleDir != NULL) {
> +    CapsuleDir->Close(CapsuleDir);
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  Build Gather list for a list of capsule images.
> +
> +  @param[in]  CapsuleBuffer    An array of pointer to capsule images
> +  @param[in]  FileSize         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                         *FileSize,
> +  IN UINTN                         CapsuleNum,
> +  OUT EFI_CAPSULE_BLOCK_DESCRIPTOR **BlockDescriptors
> +  )
> +{
> +  EFI_STATUS                    Status;
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR  *BlockDescriptors1;
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR  *BlockDescriptors2;
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR  *BlockDescriptorPre;
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR  *BlockDescriptorsHeader;
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR  *TempBlockPtr;
> +  UINT8                         *TempDataPtr;
> +  UINTN                         SizeLeft;
> +  UINTN                         Size;
> +  INT32                         Count;
> +  INT32                         Number;
> +  UINTN                         Index;
> +
> +  TempBlockPtr           = NULL;
> +  BlockDescriptors1      = NULL;
> +  BlockDescriptors2      = NULL;
> +  BlockDescriptorPre     = NULL;
> +  BlockDescriptorsHeader = NULL;
> +
> +  for (Index = 0; Index < CapsuleNum; Index++) {
> +    //
> +    // Allocate memory for the descriptors.
> +    //
> +    if (NumberOfDescriptors == 1) {
> +      Count = 2;
> +    } else {
> +      Count = (INT32)(NumberOfDescriptors + 2) / 2;
> +    }
> +
> +    Size               = Count * sizeof (EFI_CAPSULE_BLOCK_DESCRIPTOR);
> +    BlockDescriptors1  = AllocateRuntimeZeroPool (Size);
> +    if (BlockDescriptors1 == NULL) {
> +      Print (L"CapsuleApp: failed to allocate memory for descriptors\n");
> +      Status = EFI_OUT_OF_RESOURCES;
> +      goto ERREXIT;
> +    } else {
> +      Print (L"CapsuleApp: creating capsule descriptors at 0x%X\n", (UINTN)
> BlockDescriptors1);
> +      Print (L"CapsuleApp: capsule data starts          at 0x%X with size 0x%X\n",
> (UINTN) CapsuleBuffer, FileSize);
> +    }
> +
> +    //
> +    // Record descirptor header
> +    //
> +    if (Index == 0) {
> +      BlockDescriptorsHeader = BlockDescriptors1;
> +    }
> +
> +    if (BlockDescriptorPre != NULL) {
> +      BlockDescriptorPre->Union.ContinuationPointer = (UINTN) BlockDescriptors1;
> +      BlockDescriptorPre->Length = 0;
> +    }
> +
> +    //
> +    // Fill them in
> +    //
> +    TempBlockPtr  = BlockDescriptors1;
> +    TempDataPtr   = CapsuleBuffer[Index];
> +    SizeLeft      = FileSize[Index];
> +    for (Number = 0; (Number < Count - 1) && (SizeLeft != 0); Number++) {
> +      //
> +      // Divide remaining data in half
> +      //
> +      if (NumberOfDescriptors != 1) {
> +        if (SizeLeft == 1) {
> +          Size = 1;
> +        } else {
> +          Size = SizeLeft / 2;
> +        }
> +      } else {
> +        Size = SizeLeft;
> +      }
> +      TempBlockPtr->Union.DataBlock    = (UINTN)TempDataPtr;
> +      TempBlockPtr->Length  = Size;
> +      Print (L"CapsuleApp: capsule block/size              0x%X/0x%X\n", (UINTN)
> TempDataPtr, Size);
> +      SizeLeft -= Size;
> +      TempDataPtr += Size;
> +      TempBlockPtr++;
> +    }
> +
> +    //
> +    // Allocate the second list, point the first block's last entry to point
> +    // to this one, and fill this one in. Worst case is that the previous
> +    // list only had one element that pointed here, so we need at least two
> +    // elements -- one to point to all the data, another to terminate the list.
> +    //
> +    if ((NumberOfDescriptors != 1) && (SizeLeft != 0)) {
> +      Count = (INT32)(NumberOfDescriptors + 2) - Count;
> +      if (Count == 1) {
> +        Count++;
> +      }
> +
> +      Size              = Count * sizeof (EFI_CAPSULE_BLOCK_DESCRIPTOR);
> +      BlockDescriptors2 = AllocateRuntimeZeroPool (Size);
> +      if (BlockDescriptors2 == NULL) {
> +        Print (L"CapsuleApp: failed to allocate memory for descriptors\n");
> +        Status = EFI_OUT_OF_RESOURCES;
> +        goto ERREXIT;
> +      }
> +
> +      //
> +      // Point the first list's last element to point to this second list.
> +      //
> +      TempBlockPtr->Union.ContinuationPointer   = (UINTN) BlockDescriptors2;
> +
> +      TempBlockPtr->Length  = 0;
> +      TempBlockPtr = BlockDescriptors2;
> +      for (Number = 0; Number < Count - 1; Number++) {
> +        //
> +        // If second-to-last one, then dump rest to this element
> +        //
> +        if (Number == (Count - 2)) {
> +          Size = SizeLeft;
> +        } else {
> +          //
> +          // Divide remaining data in half
> +          //
> +          if (SizeLeft == 1) {
> +            Size = 1;
> +          } else {
> +            Size = SizeLeft / 2;
> +          }
> +        }
> +
> +        TempBlockPtr->Union.DataBlock    = (UINTN)TempDataPtr;
> +        TempBlockPtr->Length  = Size;
> +        Print (L"CapsuleApp: capsule block/size              0x%X/0x%X\n", (UINTN)
> TempDataPtr, Size);
> +        SizeLeft -= Size;
> +        TempDataPtr += Size;
> +        TempBlockPtr++;
> +        if (SizeLeft == 0) {
> +          break;
> +        }
> +      }
> +    }
> +
> +    BlockDescriptorPre = TempBlockPtr;
> +    BlockDescriptors1  = NULL;
> +  }
> +
> +  //
> +  // Null-terminate.
> +  //
> +  if (TempBlockPtr != NULL) {
> +    TempBlockPtr->Union.ContinuationPointer    = (UINTN)NULL;
> +    TempBlockPtr->Length  = 0;
> +    *BlockDescriptors = BlockDescriptorsHeader;
> +  }
> +
> +  return EFI_SUCCESS;
> +
> +ERREXIT:
> +  if (BlockDescriptors1 != NULL) {
> +    FreePool(BlockDescriptors1);
> +  }
> +
> +  if (BlockDescriptors2 != NULL) {
> +    FreePool(BlockDescriptors2);
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  Clear the Gather list for a list of capsule images.
> +
> +  @param[in]  BlockDescriptors The block descriptors for the capsule images
> +  @param[in]  CapsuleNum       The count of capsule images
> +**/
> +VOID
> +CleanGatherList(
> +  IN EFI_CAPSULE_BLOCK_DESCRIPTOR   *BlockDescriptors,
> +  IN UINTN                          CapsuleNum
> +  )
> +{
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR   *TempBlockPtr;
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR   *TempBlockPtr1;
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR   *TempBlockPtr2;
> +  UINTN                          Index;
> +
> +  if (BlockDescriptors != NULL) {
> +    TempBlockPtr1 = BlockDescriptors;
> +    while (1){
> +      TempBlockPtr = TempBlockPtr1;
> +      for (Index = 0; Index < CapsuleNum; Index++) {
> +        if (TempBlockPtr[Index].Length == 0) {
> +          break;
> +        }
> +      }
> +
> +      if (TempBlockPtr[Index].Union.ContinuationPointer == (UINTN)NULL) {
> +        break;
> +      }
> +
> +      TempBlockPtr2 = (VOID *) ((UINTN) TempBlockPtr->Union.ContinuationPointer);
> +      FreePool(TempBlockPtr1);
> +      TempBlockPtr1 = TempBlockPtr2;
> +    }
> +  }
> +}
> +
> +/**
> +  Print APP usage.
> +**/
> +VOID
> +PrintUsage (
> +  VOID
> +  )
> +{
> +  Print(L"CapsuleApp:  usage\n");
> +  Print(L"  CapsuleApp [-F] <Capsule...> [-NR]\n");
> +  Print(L"  CapsuleApp -S\n");
> +  Print(L"  CapsuleApp -C\n");
> +  Print(L"  CapsuleApp -P\n");
> +  Print(L"  CapsuleApp -E\n");
> +  Print(L"  CapsuleApp -G <BMP> -O <Capsule>\n");
> +  Print(L"  CapsuleApp -N <Capsule> -O <NestedCapsule>\n");
> +  Print(L"  CapsuleApp -D|-DS <Capsule>\n");
> +  Print(L"Parameter:\n");
> +  Print(L"  -F:  Put capsule file to disk.\n");
> +  Print(L"       No -F means to put capsule file in memory.\n");
> +  Print(L"  -NR: No Reset.\n");
> +  Print(L"  -S:  Dump capsule status.\n");
> +  Print(L"  -C:  Clear capsule status.\n");
> +  Print(L"  -P:  Dump FMP protocol info.\n");
> +  Print(L"  -E:  Dump ESRT table info.\n");
> +  Print(L"  -G:  Input BMP file name\n");
> +  Print(L"  -N:  Append Capsule Header accroding to Windows Firmware Update\n");
> +  Print(L"  -O:  Output Capsule file name\n");
> +  Print(L"  -D:  Dump Capsule\n");
> +  Print(L"  -DS: Dump Capsule with System FMP format\n");
> +}
> +
> +/**
> +  Update Capsule image.
> +
> +  @param[in]  ImageHandle     The image handle.
> +  @param[in]  SystemTable     The system table.
> +
> +  @retval EFI_SUCCESS            Command completed successfully.
> +  @retval EFI_INVALID_PARAMETER  Command usage error.
> +  @retval EFI_NOT_FOUND          The input file can't be found.
> +**/
> +EFI_STATUS
> +EFIAPI
> +UefiMain (
> +  IN EFI_HANDLE        ImageHandle,
> +  IN EFI_SYSTEM_TABLE  *SystemTable
> +  )
> +{
> +  EFI_STATUS                    Status;
> +  UINTN                         FileSize[MAX_CAPSULE_NUM];
> +  VOID                          *CapsuleBuffer[MAX_CAPSULE_NUM];
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR  *BlockDescriptors;
> +  EFI_CAPSULE_HEADER             *CapsuleHeaderArray[MAX_CAPSULE_NUM + 1];
> +  UINT64                         MaxCapsuleSize;
> +  EFI_RESET_TYPE                 ResetType;
> +  BOOLEAN                        NeedReset;
> +  BOOLEAN                        NoReset;
> +  BOOLEAN                        NeedCopyOnDisk;
> +  CHAR16                         *CapsuleName;
> +  UINTN                          CapsuleNum;
> +  UINTN                          Index;
> +
> +  Status = GetArg();
> +  if (EFI_ERROR(Status)) {
> +    PrintUsage();
> +    return Status;
> +  }
> +  if (Argc < 2) {
> +    PrintUsage();
> +    CleanArg();
> +    return EFI_INVALID_PARAMETER;
> +  }
> +  if ((StrCmp(Argv[1], L"-D") == 0) ||
> +      (StrCmp(Argv[1], L"-DS") == 0)) {
> +    Status = DumpCapsule();
> +    CleanArg();
> +    return Status;
> +  }
> +  if (StrCmp(Argv[1], L"-G") == 0) {
> +    Status = CreateBmpFmp();
> +    CleanArg();
> +    return Status;
> +  }
> +  if (StrCmp(Argv[1], L"-N") == 0) {
> +    Status = CreateNestedFmp();
> +    CleanArg();
> +    return Status;
> +  }
> +  if (StrCmp(Argv[1], L"-S") == 0) {
> +    Status = DmpCapsuleStatusVariable();
> +    CleanArg();
> +    return EFI_SUCCESS;
> +  }
> +  if (StrCmp(Argv[1], L"-C") == 0) {
> +    Status = ClearCapsuleStatusVariable();
> +    CleanArg();
> +    return Status;
> +  }
> +  if (StrCmp(Argv[1], L"-P") == 0) {
> +    DumpFmpData();
> +    CleanArg();
> +    return EFI_SUCCESS;
> +  }
> +  if (StrCmp(Argv[1], L"-E") == 0) {
> +    DumpEsrtData();
> +    CleanArg();
> +    return EFI_SUCCESS;
> +  }
> +  if (StrCmp(Argv[1], L"-F") == 0) {
> +    NeedCopyOnDisk = TRUE;
> +    CapsuleFirstIndex = 2;
> +  } else {
> +    NeedCopyOnDisk = FALSE;
> +    CapsuleFirstIndex = 1;
> +  }
> +  if (StrCmp(Argv[Argc - 1], L"-NR") == 0) {
> +    NoReset = TRUE;
> +    CapsuleLastIndex = Argc - 2;
> +  } else {
> +    NoReset = FALSE;
> +    CapsuleLastIndex = Argc - 1;
> +  }
> +  CapsuleNum = CapsuleLastIndex - CapsuleFirstIndex + 1;
> +
> +  if (CapsuleFirstIndex > CapsuleLastIndex) {
> +    Print(L"CapsuleApp: NO capsule image.\n");
> +    CleanArg();
> +    return EFI_UNSUPPORTED;
> +  }
> +  if (CapsuleNum > MAX_CAPSULE_NUM) {
> +    Print(L"CapsuleApp: Too many capsule images.\n");
> +    CleanArg();
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  ZeroMem(&CapsuleBuffer, sizeof(CapsuleBuffer));
> +  ZeroMem(&FileSize, sizeof(FileSize));
> +  BlockDescriptors = NULL;
> +
> +  for (Index = 0; Index < CapsuleNum; Index++) {
> +    CapsuleName = Argv[CapsuleFirstIndex + Index];
> +    Status = ReadFileToBuffer(CapsuleName, &FileSize[Index], &CapsuleBuffer[Index]);
> +    if (EFI_ERROR(Status)) {
> +      Print(L"CapsuleApp: capsule image (%s) is not found.\n", CapsuleName);
> +      goto Done;
> +    }
> +  }
> +
> +  if (NeedCopyOnDisk) {
> +    Status = CopyCapsuleToActiveEfiPartition(CapsuleBuffer, FileSize, CapsuleNum);
> +  } else {
> +    //
> +    // Every capsule use 2 descriptor 1 for data 1 for end
> +    //
> +    Status = BuildGatherList(CapsuleBuffer, FileSize, CapsuleNum, &BlockDescriptors);
> +  }
> +  if (EFI_ERROR(Status)) {
> +    goto Done;
> +  }
> +
> +  //
> +  // Call the runtime service capsule.
> +  //
> +  NeedReset = FALSE;
> +  for (Index = 0; Index < CapsuleNum; Index++) {
> +    CapsuleHeaderArray[Index] = (EFI_CAPSULE_HEADER *) CapsuleBuffer[Index];
> +    if ((CapsuleHeaderArray[Index]->Flags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET) != 0)
> {
> +      NeedReset = TRUE;
> +    }
> +  }
> +  CapsuleHeaderArray[CapsuleNum] = NULL;
> +  if (NoReset) {
> +    NeedReset = FALSE;
> +  }
> +
> +  //
> +  // Inquire platform capability of UpdateCapsule.
> +  //
> +  Status = gRT->QueryCapsuleCapabilities (CapsuleHeaderArray, CapsuleNum,
> &MaxCapsuleSize, &ResetType);
> +  if (EFI_ERROR(Status)) {
> +    Print (L"CapsuleApp: failed to query capsule capability - %r\n", Status);
> +    goto Done;
> +  }
> +
> +  for (Index = 0; Index < CapsuleNum; Index++) {
> +    if (FileSize[Index] > MaxCapsuleSize) {
> +      Print (L"CapsuleApp: capsule is too large to update, %ld is allowed\n",
> MaxCapsuleSize);
> +      Status = EFI_UNSUPPORTED;
> +      goto Done;
> +    }
> +  }
> +
> +  //
> +  // Check whether the input capsule image has the flag of persist across system
> reset.
> +  //
> +  if (NeedReset) {
> +    Status = gRT->UpdateCapsule(CapsuleHeaderArray,CapsuleNum,(UINTN)
> BlockDescriptors);
> +    if (Status != EFI_SUCCESS) {
> +      Print (L"CapsuleApp: failed to update capsule - %r\n", Status);
> +      goto Done;
> +    }
> +    //
> +    // For capsule who has reset flag, after calling UpdateCapsule service,triger a
> +    // system reset to process capsule persist across a system reset.
> +    //
> +    gRT->ResetSystem (ResetType, EFI_SUCCESS, 0, NULL);
> +  } else {
> +    //
> +    // For capsule who has no reset flag, only call UpdateCapsule Service without a
> +    // system reset. The service will process the capsule immediately.
> +    //
> +    Status = gRT->UpdateCapsule (CapsuleHeaderArray,CapsuleNum,(UINTN)
> BlockDescriptors);
> +    if (Status != EFI_SUCCESS) {
> +      Print (L"CapsuleApp: failed to update capsule - %r\n", Status);
> +    }
> +  }
> +
> +  Status = EFI_SUCCESS;
> +
> +Done:
> +  for (Index = 0; Index < CapsuleNum; Index++) {
> +    if (CapsuleBuffer[Index] != NULL) {
> +      FreePool (CapsuleBuffer[Index]);
> +    }
> +  }
> +
> +  CleanGatherList(BlockDescriptors, CapsuleNum);
> +  CleanArg();
> +
> +  return Status;
> +}
> diff --git a/MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf
> b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf
> new file mode 100644
> index 0000000..7ee44fc
> --- /dev/null
> +++ b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf
> @@ -0,0 +1,71 @@
> +##  @file
> +#  A shell application that triggers capsule update process.
> +#
> +# This application can trigger capsule update process. It can also
> +# generate capsule image, or dump capsule variable information.
> +#
> +#  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
> +#  This program and the accompanying materials
> +#  are licensed and made available under the terms and conditions of the BSD License
> +#  which accompanies this distribution.  The full text of the license may be found at
> +#  http://opensource.org/licenses/bsd-license.php
> +#
> +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +#
> +##
> +
> +[Defines]
> +  INF_VERSION                    = 0x00010006
> +  BASE_NAME                      = CapsuleApp
> +  MODULE_UNI_FILE                = CapsuleApp.uni
> +  FILE_GUID                      = 4CEF31DA-8682-4274-9CC4-AEE7516A5E7B
> +  MODULE_TYPE                    = UEFI_APPLICATION
> +  VERSION_STRING                 = 1.0
> +  ENTRY_POINT                    = UefiMain
> +
> +#
> +# The following information is for reference only and not required by the build tools.
> +#
> +#  VALID_ARCHITECTURES           = IA32 X64
> +#
> +
> +[Sources]
> +  CapsuleApp.c
> +  CapsuleDump.c
> +  AppSupport.c
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +
> +[Guids]
> +  gEfiFileInfoGuid
> +  gEfiPartTypeSystemPartGuid
> +  gEfiGlobalVariableGuid
> +  gEfiCapsuleReportGuid
> +  gEfiFmpCapsuleGuid
> +  gWindowsUxCapsuleGuid
> +  gEfiCertTypeRsa2048Sha256Guid
> +  gEfiCertPkcs7Guid
> +  gEfiSystemResourceTableGuid
> +
> +[Protocols]
> +  gEfiLoadedImageProtocolGuid
> +  gEfiSimpleFileSystemProtocolGuid
> +  gEfiGraphicsOutputProtocolGuid
> +  gEfiFirmwareManagementProtocolGuid
> +
> +[LibraryClasses]
> +  BaseLib
> +  UefiApplicationEntryPoint
> +  DebugLib
> +  MemoryAllocationLib
> +  UefiBootServicesTableLib
> +  UefiRuntimeServicesTableLib
> +  UefiLib
> +  PrintLib
> +  EdkiiSystemCapsuleLib
> +
> +[UserExtensions.TianoCore."ExtraFiles"]
> +  CapsuleAppExtra.uni
> diff --git a/MdeModulePkg/Application/CapsuleApp/CapsuleApp.uni
> b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.uni
> new file mode 100644
> index 0000000..54d6e12
> --- /dev/null
> +++ b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.uni
> @@ -0,0 +1,22 @@
> +// /** @file
> +// A shell application that triggers capsule update process.
> +//
> +// This application can trigger capsule update process. It can also
> +// generate capsule image, or dump capsule variable information.
> +//
> +// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
> +//
> +// This program and the accompanying materials
> +// are licensed and made available under the terms and conditions of the BSD License
> +// which accompanies this distribution. The full text of the license may be found at
> +// http://opensource.org/licenses/bsd-license.php
> +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +//
> +// **/
> +
> +
> +#string STR_MODULE_ABSTRACT             #language en-US "A shell application that
> triggers capsule update process."
> +
> +#string STR_MODULE_DESCRIPTION          #language en-US "This application can trigger
> capsule update process. It can also generate capsule image, or dump capsule variable
> information."
> +
> diff --git a/MdeModulePkg/Application/CapsuleApp/CapsuleAppExtra.uni
> b/MdeModulePkg/Application/CapsuleApp/CapsuleAppExtra.uni
> new file mode 100644
> index 0000000..b5a8840
> --- /dev/null
> +++ b/MdeModulePkg/Application/CapsuleApp/CapsuleAppExtra.uni
> @@ -0,0 +1,19 @@
> +// /** @file
> +// CapsuleApp Localized Strings and Content
> +//
> +// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
> +//
> +// This program and the accompanying materials
> +// are licensed and made available under the terms and conditions of the BSD License
> +// which accompanies this distribution. The full text of the license may be found at
> +// http://opensource.org/licenses/bsd-license.php
> +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +//
> +// **/
> +
> +#string STR_PROPERTIES_MODULE_NAME
> +#language en-US
> +"Capsule Application"
> +
> +
> diff --git a/MdeModulePkg/Application/CapsuleApp/CapsuleDump.c
> b/MdeModulePkg/Application/CapsuleApp/CapsuleDump.c
> new file mode 100644
> index 0000000..c56f41f
> --- /dev/null
> +++ b/MdeModulePkg/Application/CapsuleApp/CapsuleDump.c
> @@ -0,0 +1,840 @@
> +/** @file
> +  Dump Capsule image information.
> +
> +  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the BSD License
> +  which accompanies this distribution.  The full text of the license may be found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +
> +**/
> +
> +#include <PiDxe.h>
> +#include <Library/BaseLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/UefiRuntimeServicesTableLib.h>
> +#include <Library/UefiLib.h>
> +#include <Library/PrintLib.h>
> +#include <Library/EdkiiSystemCapsuleLib.h>
> +#include <Protocol/FirmwareManagement.h>
> +#include <Guid/ImageAuthentication.h>
> +#include <Guid/EdkiiSystemFmpCapsule.h>
> +#include <Guid/CapsuleReport.h>
> +#include <Guid/SystemResourceTable.h>
> +#include <Guid/FmpCapsule.h>
> +#include <IndustryStandard/WindowsUxCapsule.h>
> +
> +/**
> +  Read a file.
> +
> +  @param FileName        The file to be read.
> +  @param BufferSize      The file buffer size
> +  @param Buffer          The file buffer
> +
> +  @retval EFI_SUCCESS    Read file successfully
> +  @retval EFI_NOT_FOUND  File not found
> +**/
> +EFI_STATUS
> +ReadFileToBuffer(
> +  IN  CHAR16                               *FileName,
> +  OUT UINTN                                *BufferSize,
> +  OUT VOID                                 **Buffer
> +  );
> +
> +extern UINTN  Argc;
> +extern CHAR16 *Argv[];
> +
> +/**
> +  Dump UX capsule information.
> +
> +  @param CapsuleHeader      The UX capsule header
> +**/
> +VOID
> +DumpUxCapsule(
> +  IN EFI_CAPSULE_HEADER  *CapsuleHeader
> +  )
> +{
> +  EFI_DISPLAY_CAPSULE                           *DisplayCapsule;
> +  DisplayCapsule = (EFI_DISPLAY_CAPSULE *)CapsuleHeader;
> +  Print(L"[UxCapusule]\n");
> +  Print(L"CapsuleHeader:\n");
> +  Print(L"  CapsuleGuid      - %g\n", &DisplayCapsule->CapsuleHeader.CapsuleGuid);
> +  Print(L"  HeaderSize       - 0x%x\n", DisplayCapsule->CapsuleHeader.HeaderSize);
> +  Print(L"  Flags            - 0x%x\n", DisplayCapsule->CapsuleHeader.Flags);
> +  Print(L"  CapsuleImageSize - 0x%x\n", DisplayCapsule-
> >CapsuleHeader.CapsuleImageSize);
> +  Print(L"ImagePayload:\n");
> +  Print(L"  Version          - 0x%x\n", DisplayCapsule->ImagePayload.Version);
> +  Print(L"  Checksum         - 0x%x\n", DisplayCapsule->ImagePayload.Checksum);
> +  Print(L"  ImageType        - 0x%x\n", DisplayCapsule->ImagePayload.ImageType);
> +  Print(L"  Mode             - 0x%x\n", DisplayCapsule->ImagePayload.Mode);
> +  Print(L"  OffsetX          - 0x%x\n", DisplayCapsule->ImagePayload.OffsetX);
> +  Print(L"  OffsetY          - 0x%x\n", DisplayCapsule->ImagePayload.OffsetY);
> +}
> +
> +/**
> +  Dump FMP image authentication information.
> +
> +  @param Image      The FMP capsule image
> +  @param ImageSize  The size of the FMP capsule image in bytes.
> +
> +  @return the size of FMP authentication.
> +**/
> +UINTN
> +DumpImageAuthentication(
> +  IN VOID   *Image,
> +  IN UINTN  ImageSize
> +  )
> +{
> +  EFI_FIRMWARE_IMAGE_AUTHENTICATION             *ImageAuthentication;
> +
> +  ImageAuthentication = Image;
> +  if (CompareGuid(&ImageAuthentication->AuthInfo.CertType, &gEfiCertPkcs7Guid) ||
> +      CompareGuid(&ImageAuthentication->AuthInfo.CertType,
> &gEfiCertTypeRsa2048Sha256Guid)) {
> +    Print(L"[ImageAuthentication]\n");
> +    Print(L"  MonotonicCount   - 0x%lx\n", ImageAuthentication->MonotonicCount);
> +    Print(L"WIN_CERTIFICATE:\n");
> +    Print(L"  dwLength         - 0x%x\n", ImageAuthentication->AuthInfo.Hdr.dwLength);
> +    Print(L"  wRevision        - 0x%x\n", ImageAuthentication-
> >AuthInfo.Hdr.wRevision);
> +    Print(L"  wCertificateType - 0x%x\n", ImageAuthentication-
> >AuthInfo.Hdr.wCertificateType);
> +    Print(L"  CertType         - %g\n", &ImageAuthentication->AuthInfo.CertType);
> +    return sizeof(ImageAuthentication->MonotonicCount) + ImageAuthentication-
> >AuthInfo.Hdr.dwLength;
> +  } else {
> +    return 0;
> +  }
> +}
> +
> +/**
> +  Dump EDKII system FMP capsule.
> +
> +  @param Image      The EDKII system FMP capsule.
> +  @param ImageSize  The size of the EDKII system FMP capsule in bytes.
> +**/
> +VOID
> +DumpEdkiiSystemFmpCapsule(
> +  IN VOID   *Image,
> +  IN UINTN  ImageSize
> +  )
> +{
> +  UINTN                                         ImageOffset;
> +  VOID                                          *BiosImage;
> +  UINTN                                         BiosImageSize;
> +  BOOLEAN                                       Result;
> +  EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR        *TempImageFmpInfo;
> +  EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR        *ImageFmpInfo;
> +  UINTN                                         ImageFmpInfoSize;
> +
> +  //
> +  // We do not know if there is EFI_FIRMWARE_IMAGE_AUTHENTICATION.
> +  // so just *try* to parse it
> +  //
> +  ImageOffset = DumpImageAuthentication(Image, ImageSize);
> +  Image = (UINT8 *)Image + ImageOffset;
> +  ImageSize -= ImageOffset;
> +  Print(L"[Image]\n");
> +  Print(L"  ImageSize   - 0x%x\n", ImageSize);
> +
> +  Result = ExtractConfigImage(Image, ImageSize, &BiosImage, &BiosImageSize);
> +  if (Result) {
> +    Print(L"  ConfigFileSize  - 0x%x\n", BiosImageSize);
> +  }
> +  Result = ExtractDriverFvImage(Image, ImageSize, &BiosImage, &BiosImageSize);
> +  if (Result) {
> +    Print(L"  DriverFvSize    - 0x%x\n", BiosImageSize);
> +  }
> +  Result = ExtractSystemFirmwareImage(Image, ImageSize, &BiosImage, &BiosImageSize);
> +  if (Result) {
> +    Print(L"  BiosImageSize   - 0x%x\n", BiosImageSize);
> +  }
> +  Result = ExtractSystemFirmwareImageFmpInfo(BiosImage, BiosImageSize,
> &TempImageFmpInfo, &ImageFmpInfoSize);
> +  if (Result) {
> +    ImageFmpInfo = AllocateCopyPool(ImageFmpInfoSize, TempImageFmpInfo);
> +    if (ImageFmpInfo != NULL) {
> +      Print(L"[ImageFmpInfo]\n");
> +      Print(L"  Signature                      - 0x%x\n", ImageFmpInfo->Signature);
> +      Print(L"  HeaderLength                   - 0x%x\n", ImageFmpInfo->HeaderLength);
> +      Print(L"  Length                         - 0x%x\n", ImageFmpInfo->Length);
> +      Print(L"  PackageVersion                 - 0x%x\n", ImageFmpInfo-
> >PackageVersion);
> +      Print(L"  PackageVersionNameStringOffset - 0x%x\n", ImageFmpInfo-
> >PackageVersionNameStringOffset);
> +      if (ImageFmpInfo->PackageVersionNameStringOffset != 0) {
> +        Print(L"                                 - %s\n", (UINT8 *)ImageFmpInfo +
> ImageFmpInfo->PackageVersionNameStringOffset);
> +      }
> +      Print(L"  ImageIndex                     - 0x%x\n", ImageFmpInfo->ImageIndex);
> +      Print(L"  ImageTypeId                    - %g\n", &ImageFmpInfo->ImageTypeId);
> +      Print(L"  ImageId                        - 0x%lx\n", ImageFmpInfo->ImageId);
> +      Print(L"  ImageIdNameStringOffset        - 0x%x\n", ImageFmpInfo-
> >ImageIdNameStringOffset);
> +      if (ImageFmpInfo->ImageIdNameStringOffset != 0) {
> +        Print(L"                                 - %s\n", (UINT8 *)ImageFmpInfo +
> ImageFmpInfo->ImageIdNameStringOffset);
> +      }
> +      Print(L"  Version                        - 0x%x\n", ImageFmpInfo->Version);
> +      Print(L"  VersionNameStringOffset        - 0x%x\n", ImageFmpInfo-
> >VersionNameStringOffset);
> +      if (ImageFmpInfo->VersionNameStringOffset != 0) {
> +        Print(L"                                 - %s\n", (UINT8 *)ImageFmpInfo +
> ImageFmpInfo->VersionNameStringOffset);
> +      }
> +      Print(L"  Size                           - 0x%lx\n", ImageFmpInfo->Size);
> +      Print(L"  AttributesSupported            - 0x%lx\n", ImageFmpInfo-
> >AttributesSupported);
> +      Print(L"  AttributesSetting              - 0x%lx\n", ImageFmpInfo-
> >AttributesSetting);
> +      Print(L"  Compatibilities                - 0x%lx\n", ImageFmpInfo-
> >Compatibilities);
> +      Print(L"  LowestSupportedImageVersion    - 0x%x\n", ImageFmpInfo-
> >LowestSupportedImageVersion);
> +      Print(L"  LastAttemptVersion             - 0x%x\n", ImageFmpInfo-
> >LastAttemptVersion);
> +      Print(L"  LastAttemptStatus              - 0x%x\n", ImageFmpInfo-
> >LastAttemptStatus);
> +      Print(L"  HardwareInstance               - 0x%lx\n", ImageFmpInfo-
> >HardwareInstance);
> +      Print(L"  Version                        - 0x%x\n", ImageFmpInfo->Version);
> +      FreePool(ImageFmpInfo);
> +    }
> +  }
> +}
> +
> +/**
> +  Dump a non-nested FMP capsule.
> +
> +  @param  CapsuleHeader  A pointer to CapsuleHeader
> +  @param  IsSystemFmp    If it is a system FMP
> +**/
> +VOID
> +DumpFmpCapsule(
> +  IN EFI_CAPSULE_HEADER  *CapsuleHeader,
> +  IN BOOLEAN             IsSystemFmp
> +  )
> +{
> +  EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER        *FmpCapsuleHeader;
> +  UINT64                                        *ItemOffsetList;
> +  UINTN                                         Index;
> +  UINTN                                         Count;
> +  EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER  *FmpImageHeader;
> +  VOID                                          *Image;
> +
> +  Print(L"[FmpCapusule]\n");
> +  Print(L"CapsuleHeader:\n");
> +  Print(L"  CapsuleGuid      - %g\n", &CapsuleHeader->CapsuleGuid);
> +  Print(L"  HeaderSize       - 0x%x\n", CapsuleHeader->HeaderSize);
> +  Print(L"  Flags            - 0x%x\n", CapsuleHeader->Flags);
> +  Print(L"  CapsuleImageSize - 0x%x\n", CapsuleHeader->CapsuleImageSize);
> +
> +  FmpCapsuleHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *)((UINT8 *)CapsuleHeader
> + CapsuleHeader->HeaderSize);
> +  ItemOffsetList = (UINT64 *)(FmpCapsuleHeader + 1);
> +  Print(L"FmpHeader:\n");
> +  Print(L"  Version             - 0x%x\n", FmpCapsuleHeader->Version);
> +  Print(L"  EmbeddedDriverCount - 0x%x\n", FmpCapsuleHeader->EmbeddedDriverCount);
> +  Print(L"  PayloadItemCount    - 0x%x\n", FmpCapsuleHeader->PayloadItemCount);
> +  Count = FmpCapsuleHeader->EmbeddedDriverCount + FmpCapsuleHeader->PayloadItemCount;
> +  for (Index = 0; Index < Count; Index++) {
> +    Print(L"  Offset[%d]           - 0x%x\n", Index, ItemOffsetList[Index]);
> +  }
> +
> +  for (Index = FmpCapsuleHeader->EmbeddedDriverCount; Index < Count; Index++) {
> +    Print(L"FmpPayload[%d] ImageHeader:\n", Index);
> +    FmpImageHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *)((UINT8
> *)FmpCapsuleHeader + ItemOffsetList[Index]);
> +    Print(L"  Version                - 0x%x\n", FmpImageHeader->Version);
> +    Print(L"  UpdateImageTypeId      - %g\n", &FmpImageHeader->UpdateImageTypeId);
> +    Print(L"  UpdateImageIndex       - 0x%x\n", FmpImageHeader->UpdateImageIndex);
> +    Print(L"  UpdateImageSize        - 0x%x\n", FmpImageHeader->UpdateImageSize);
> +    Print(L"  UpdateVendorCodeSize   - 0x%x\n", FmpImageHeader->UpdateVendorCodeSize);
> +    if (FmpImageHeader->Version >=
> EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {
> +      Print(L"  UpdateHardwareInstance - 0x%lx\n", FmpImageHeader-
> >UpdateHardwareInstance);
> +    }
> +    if (FmpImageHeader->Version >=
> EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {
> +      Image = (UINT8 *)(FmpImageHeader + 1);
> +    }  else {
> +      Image = (UINT8 *)FmpImageHeader +
> OFFSET_OF(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER, UpdateHardwareInstance);
> +    }
> +    if (IsSystemFmp) {
> +      DumpEdkiiSystemFmpCapsule(Image, FmpImageHeader->UpdateImageSize);
> +    }
> +  }
> +}
> +
> +/**
> +  Return if there is a FMP header below capsule header.
> +
> +  @param[in] CapsuleHeader A pointer to EFI_CAPSULE_HEADER
> +
> +  @retval TRUE  There is a FMP header below capsule header.
> +  @retval FALSE There is not a FMP header below capsule header
> +**/
> +BOOLEAN
> +IsNestedFmpCapsule(
> +  IN EFI_CAPSULE_HEADER         *CapsuleHeader
> +  )
> +{
> +  EFI_STATUS                 Status;
> +  EFI_SYSTEM_RESOURCE_TABLE  *Esrt;
> +  EFI_SYSTEM_RESOURCE_ENTRY  *EsrtEntry;
> +  UINTN                      Index;
> +  BOOLEAN                    EsrtGuidFound;
> +  EFI_CAPSULE_HEADER         *NestedCapsuleHeader;
> +  UINTN                      NestedCapsuleSize;
> +
> +  //
> +  // Check ESRT
> +  //
> +  EsrtGuidFound = FALSE;
> +  Status = EfiGetSystemConfigurationTable(&gEfiSystemResourceTableGuid, (VOID
> **)&Esrt);
> +  if (!EFI_ERROR(Status)) {
> +    EsrtEntry = (VOID *)(Esrt + 1);
> +    for (Index = 0; Index < Esrt->FwResourceCount; Index++, EsrtEntry++) {
> +      if (CompareGuid(&EsrtEntry->FwClass, &CapsuleHeader->CapsuleGuid)) {
> +        EsrtGuidFound = TRUE;
> +        break;
> +      }
> +    }
> +  }
> +
> +  if (!EsrtGuidFound) {
> +    return FALSE;
> +  }
> +
> +  //
> +  // Check nested capsule header
> +  // FMP GUID after ESRT one
> +  //
> +  NestedCapsuleHeader = (EFI_CAPSULE_HEADER *)((UINT8 *)CapsuleHeader + CapsuleHeader-
> >HeaderSize);
> +  NestedCapsuleSize = (UINTN)CapsuleHeader + CapsuleHeader->HeaderSize -
> (UINTN)NestedCapsuleHeader;
> +  if (NestedCapsuleSize < sizeof(EFI_CAPSULE_HEADER)) {
> +    return FALSE;
> +  }
> +  if (!CompareGuid(&NestedCapsuleHeader->CapsuleGuid, &gEfiFmpCapsuleGuid)) {
> +    return FALSE;
> +  }
> +  return TRUE;
> +}
> +
> +/**
> +  Dump capsule information
> +
> +  @retval EFI_SUCCESS            The capsule information is dumped.
> +  @retval EFI_UNSUPPORTED        Input parameter is not valid.
> +**/
> +EFI_STATUS
> +DumpCapsule(
> +  VOID
> +  )
> +{
> +  CHAR16                                        *CapsuleName;
> +  VOID                                          *Buffer;
> +  UINTN                                         FileSize;
> +  BOOLEAN                                       IsSystemFmp;
> +  EFI_CAPSULE_HEADER                            *CapsuleHeader;
> +  EFI_STATUS                                    Status;
> +
> +  if (Argc != 3) {
> +    Print(L"CapsuleApp: Invalid Parameter.\n");
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  IsSystemFmp = FALSE;
> +  if (StrCmp(Argv[1], L"-DS") == 0) {
> +    IsSystemFmp = TRUE;
> +  }
> +
> +  CapsuleName = Argv[2];
> +  Status = ReadFileToBuffer(CapsuleName, &FileSize, &Buffer);
> +  if (EFI_ERROR(Status)) {
> +    Print(L"CapsuleApp: Capsule (%s) is not found.\n", CapsuleName);
> +    goto Done;
> +  }
> +
> +  CapsuleHeader = Buffer;
> +  if (CompareGuid(&CapsuleHeader->CapsuleGuid, &gWindowsUxCapsuleGuid)) {
> +    DumpUxCapsule(CapsuleHeader);
> +    Status = EFI_SUCCESS;
> +    goto Done;
> +  }
> +
> +  if (CompareGuid(&CapsuleHeader->CapsuleGuid, &gEfiFmpCapsuleGuid)) {
> +    DumpFmpCapsule(CapsuleHeader, IsSystemFmp);
> +  }
> +  if (IsNestedFmpCapsule(CapsuleHeader)) {
> +    Print(L"[NestedCapusule]\n");
> +    Print(L"CapsuleHeader:\n");
> +    Print(L"  CapsuleGuid      - %g\n", &CapsuleHeader->CapsuleGuid);
> +    Print(L"  HeaderSize       - 0x%x\n", CapsuleHeader->HeaderSize);
> +    Print(L"  Flags            - 0x%x\n", CapsuleHeader->Flags);
> +    Print(L"  CapsuleImageSize - 0x%x\n", CapsuleHeader->CapsuleImageSize);
> +    DumpFmpCapsule((EFI_CAPSULE_HEADER *)((UINTN)CapsuleHeader + CapsuleHeader-
> >HeaderSize), IsSystemFmp);
> +  }
> +
> +Done:
> +  FreePool(Buffer);
> +  return Status;
> +}
> +
> +/**
> +  Dump capsule status variable.
> +
> +  @retval EFI_SUCCESS            The capsule status variable is dumped.
> +  @retval EFI_UNSUPPORTED        Input parameter is not valid.
> +**/
> +EFI_STATUS
> +DmpCapsuleStatusVariable(
> +  VOID
> +  )
> +{
> +  EFI_STATUS                          Status;
> +  UINT32                              Index;
> +  CHAR16                              CapsuleVarName[20];
> +  CHAR16                              *TempVarName;
> +  EFI_CAPSULE_RESULT_VARIABLE_HEADER  *CapsuleResult;
> +  EFI_CAPSULE_RESULT_VARIABLE_FMP     *CapsuleResultFmp;
> +  UINTN                               CapsuleFileNameSize;
> +  CHAR16                              CapsuleIndexData[12];
> +  CHAR16                              *CapsuleIndex;
> +
> +  Status = GetVariable2(
> +             L"CapsuleMax",
> +             &gEfiCapsuleReportGuid,
> +             (VOID **)&CapsuleIndex,
> +             NULL
> +             );
> +  if (!EFI_ERROR(Status)) {
> +    CopyMem(CapsuleIndexData, CapsuleIndex, 11 * sizeof(CHAR16));
> +    CapsuleIndexData[11] = 0;
> +    Print(L"CapsuleMax - %s\n", CapsuleIndexData);
> +    FreePool(CapsuleIndex);
> +  }
> +  Status = GetVariable2(
> +             L"CapsuleLast",
> +             &gEfiCapsuleReportGuid,
> +             (VOID **)&CapsuleIndex,
> +             NULL
> +             );
> +  if (!EFI_ERROR(Status)) {
> +    CopyMem(CapsuleIndexData, CapsuleIndex, 11 * sizeof(CHAR16));
> +    CapsuleIndexData[11] = 0;
> +    Print(L"CapsuleLast - %s\n", CapsuleIndexData);
> +    FreePool(CapsuleIndex);
> +  }
> +
> +
> +  StrCpyS (CapsuleVarName, sizeof(CapsuleVarName)/sizeof(CapsuleVarName[0]),
> L"Capsule");
> +  TempVarName = CapsuleVarName + StrLen (CapsuleVarName);
> +  Index = 0;
> +
> +  while (TRUE) {
> +    UnicodeSPrint (TempVarName, 5 * sizeof(CHAR16), L"%04x", Index);
> +
> +    Status = GetVariable2 (
> +               CapsuleVarName,
> +               &gEfiCapsuleReportGuid,
> +               (VOID **) &CapsuleResult,
> +               NULL
> +               );
> +    if (Status == EFI_NOT_FOUND) {
> +      break;
> +    } else if (EFI_ERROR(Status)) {
> +      continue;
> +    }
> +
> +    //
> +    // display capsule process status
> +    //
> +    if (CapsuleResult->VariableTotalSize >=
> sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER)) {
> +      Print (L"CapsuleName: %s\n", CapsuleVarName);
> +      Print (L"  Capsule Guid: %g\n", &CapsuleResult->CapsuleGuid);
> +      Print (L"  Capsule ProcessedTime: %t\n", &CapsuleResult->CapsuleProcessed);
> +      Print (L"  Capsule Status: %r\n", CapsuleResult->CapsuleStatus);
> +    }
> +
> +    if (CompareGuid(&CapsuleResult->CapsuleGuid, &gEfiFmpCapsuleGuid)) {
> +      if (CapsuleResult->VariableTotalSize >=
> sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER) + sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP)) {
> +        CapsuleResultFmp = (EFI_CAPSULE_RESULT_VARIABLE_FMP *)(CapsuleResult + 1);
> +        Print(L"  Capsule FMP Version: 0x%x\n", CapsuleResultFmp->Version);
> +        Print(L"  Capsule FMP PayloadIndex: 0x%x\n", CapsuleResultFmp->PayloadIndex);
> +        Print(L"  Capsule FMP UpdateImageIndex: 0x%x\n", CapsuleResultFmp-
> >UpdateImageIndex);
> +        Print(L"  Capsule FMP UpdateImageTypeId: %g\n", &CapsuleResultFmp-
> >UpdateImageTypeId);
> +        if (CapsuleResult->VariableTotalSize >
> sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER) + sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP)) {
> +          Print(L"  Capsule FMP CapsuleFileName: %s\n", (CapsuleResultFmp + 1));
> +          CapsuleFileNameSize = StrSize((CHAR16 *)(CapsuleResultFmp + 1));
> +          if (CapsuleResult->VariableTotalSize >
> sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER) + sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP) +
> CapsuleFileNameSize) {
> +            Print(L"  Capsule FMP CapsuleTarget: %s\n", (UINT8 *)(CapsuleResultFmp +
> 1) + CapsuleFileNameSize);
> +          }
> +        }
> +      }
> +    }
> +
> +    FreePool(CapsuleResult);
> +
> +    Index++;
> +    if (Index > 0xFFFF) {
> +      break;
> +    }
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +CHAR8 *mFwTypeString[] = {
> +  "Unknown",
> +  "SystemFirmware",
> +  "DeviceFirmware",
> +  "UefiDriver",
> +};
> +
> +CHAR8 *mLastAttemptStatusString[] = {
> +  "Success",
> +  "Error: Unsuccessful",
> +  "Error: Insufficient Resources",
> +  "Error: Incorrect Version",
> +  "Error: Invalid Format",
> +  "Error: Auth Error",
> +  "Error: Power Event AC",
> +  "Error: Power Event Battery",
> +};
> +
> +/**
> +  Convert FwType to a string.
> +
> +  @param FwType  FwType in ESRT
> +
> +  @return a string for FwType.
> +**/
> +CHAR8 *
> +FwTypeToString(
> +  IN UINT32 FwType
> +  )
> +{
> +  if (FwType < sizeof(mFwTypeString) / sizeof(mFwTypeString[0])) {
> +    return mFwTypeString[FwType];
> +  } else {
> +    return "Invalid";
> +  }
> +}
> +
> +/**
> +  Convert LastAttemptStatus to a string.
> +
> +  @param LastAttemptStatus  LastAttemptStatus in FMP or ESRT
> +
> +  @return a string for LastAttemptStatus.
> +**/
> +CHAR8 *
> +LastAttemptStatusToString(
> +  IN UINT32 LastAttemptStatus
> +  )
> +{
> +  if (LastAttemptStatus < sizeof(mLastAttemptStatusString) /
> sizeof(mLastAttemptStatusString[0])) {
> +    return mLastAttemptStatusString[LastAttemptStatus];
> +  } else {
> +    return "Error: Unknown";
> +  }
> +}
> +
> +/**
> +  Dump ESRT entry.
> +
> +  @param EsrtEntry  ESRT entry
> +**/
> +VOID
> +DumpEsrtEntry(
> +  IN EFI_SYSTEM_RESOURCE_ENTRY  *EsrtEntry
> +  )
> +{
> +  Print(L"  FwClass                  - %g\n", &EsrtEntry->FwClass);
> +  Print(L"  FwType                   - 0x%x (%a)\n", EsrtEntry->FwType,
> FwTypeToString(EsrtEntry->FwType));
> +  Print(L"  FwVersion                - 0x%x\n", EsrtEntry->FwVersion);
> +  Print(L"  LowestSupportedFwVersion - 0x%x\n", EsrtEntry->LowestSupportedFwVersion);
> +  Print(L"  CapsuleFlags             - 0x%x\n", EsrtEntry->CapsuleFlags);
> +  Print(L"    PERSIST_ACROSS_RESET   - 0x%x\n", EsrtEntry->CapsuleFlags &
> CAPSULE_FLAGS_PERSIST_ACROSS_RESET);
> +  Print(L"    POPULATE_SYSTEM_TABLE  - 0x%x\n", EsrtEntry->CapsuleFlags &
> CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE);
> +  Print(L"    INITIATE_RESET         - 0x%x\n", EsrtEntry->CapsuleFlags &
> CAPSULE_FLAGS_INITIATE_RESET);
> +  Print(L"  LastAttemptVersion       - 0x%x\n", EsrtEntry->LastAttemptVersion);
> +  Print(L"  LastAttemptStatus        - 0x%x (%a)\n", EsrtEntry->LastAttemptStatus,
> LastAttemptStatusToString(EsrtEntry->LastAttemptStatus));
> +}
> +
> +/**
> +  Dump ESRT table.
> +
> +  @param Esrt  ESRT table
> +**/
> +VOID
> +DumpEsrt(
> +  IN EFI_SYSTEM_RESOURCE_TABLE  *Esrt
> +  )
> +{
> +  UINTN                      Index;
> +  EFI_SYSTEM_RESOURCE_ENTRY  *EsrtEntry;
> +
> +  Print(L"EFI_SYSTEM_RESOURCE_TABLE:\n");
> +  Print(L"FwResourceCount    - 0x%x\n", Esrt->FwResourceCount);
> +  Print(L"FwResourceCountMax - 0x%x\n", Esrt->FwResourceCountMax);
> +  Print(L"FwResourceVersion  - 0x%lx\n", Esrt->FwResourceVersion);
> +
> +  EsrtEntry = (VOID *)(Esrt + 1);
> +  for (Index = 0; Index < Esrt->FwResourceCount; Index++) {
> +    Print(L"EFI_SYSTEM_RESOURCE_ENTRY (%d):\n", Index);
> +    DumpEsrtEntry(EsrtEntry);
> +    EsrtEntry++;
> +  }
> +}
> +
> +/**
> +  Dump ESRT info.
> +**/
> +VOID
> +DumpEsrtData (
> +  VOID
> +  )
> +{
> +  EFI_STATUS                 Status;
> +  EFI_SYSTEM_RESOURCE_TABLE  *Esrt;
> +
> +  Print(L"##############\n");
> +  Print(L"# ESRT TABLE #\n");
> +  Print(L"##############\n");
> +
> +  Status = EfiGetSystemConfigurationTable (&gEfiSystemResourceTableGuid, (VOID
> **)&Esrt);
> +  if (EFI_ERROR(Status)) {
> +    Print(L"ESRT - %r\n", Status);
> +    return;
> +  }
> +  DumpEsrt(Esrt);
> +  Print(L"\n");
> +}
> +
> +/**
> +  Dump FMP information.
> +
> +  @param ImageInfoSize       The size of ImageInfo, in bytes.
> +  @param ImageInfo           A pointer to EFI_FIRMWARE_IMAGE_DESCRIPTOR.
> +  @param DescriptorVersion   The version of EFI_FIRMWARE_IMAGE_DESCRIPTOR.
> +  @param DescriptorCount     The count of EFI_FIRMWARE_IMAGE_DESCRIPTOR.
> +  @param DescriptorSize      The size of an individual EFI_FIRMWARE_IMAGE_DESCRIPTOR,
> in bytes.
> +  @param PackageVersion      The version of package.
> +  @param PackageVersionName  The version name of package.
> +**/
> +VOID
> +DumpFmpImageInfo(
> +  IN UINTN                           ImageInfoSize,
> +  IN EFI_FIRMWARE_IMAGE_DESCRIPTOR   *ImageInfo,
> +  IN UINT32                          DescriptorVersion,
> +  IN UINT8                           DescriptorCount,
> +  IN UINTN                           DescriptorSize,
> +  IN UINT32                          PackageVersion,
> +  IN CHAR16                          *PackageVersionName
> +  )
> +{
> +  EFI_FIRMWARE_IMAGE_DESCRIPTOR                 *CurrentImageInfo;
> +  UINTN                                         Index;
> +
> +  Print(L"  DescriptorVersion  - 0x%x\n", DescriptorVersion);
> +  Print(L"  DescriptorCount    - 0x%x\n", DescriptorCount);
> +  Print(L"  DescriptorSize     - 0x%x\n", DescriptorSize);
> +  Print(L"  PackageVersion     - 0x%x\n", PackageVersion);
> +  Print(L"  PackageVersionName - \"%s\"\n", PackageVersionName);
> +  CurrentImageInfo = ImageInfo;
> +  for (Index = 0; Index < DescriptorCount; Index++) {
> +    Print(L"  ImageDescriptor (%d)\n", Index);
> +    Print(L"    ImageIndex                  - 0x%x\n", CurrentImageInfo->ImageIndex);
> +    Print(L"    ImageTypeId                 - %g\n", &CurrentImageInfo->ImageTypeId);
> +    Print(L"    ImageId                     - 0x%lx\n", CurrentImageInfo->ImageId);
> +    Print(L"    ImageIdName                 - \"%s\"\n", CurrentImageInfo-
> >ImageIdName);
> +    Print(L"    Version                     - 0x%x\n", CurrentImageInfo->Version);
> +    Print(L"    VersionName                 - \"%s\"\n", CurrentImageInfo-
> >VersionName);
> +    Print(L"    Size                        - 0x%x\n", CurrentImageInfo->Size);
> +    Print(L"    AttributesSupported         - 0x%lx\n", CurrentImageInfo-
> >AttributesSupported);
> +    Print(L"      IMAGE_UPDATABLE           - 0x%lx\n", CurrentImageInfo-
> >AttributesSupported & IMAGE_ATTRIBUTE_IMAGE_UPDATABLE);
> +    Print(L"      RESET_REQUIRED            - 0x%lx\n", CurrentImageInfo-
> >AttributesSupported & IMAGE_ATTRIBUTE_RESET_REQUIRED);
> +    Print(L"      AUTHENTICATION_REQUIRED   - 0x%lx\n", CurrentImageInfo-
> >AttributesSupported & IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);
> +    Print(L"      IN_USE                    - 0x%lx\n", CurrentImageInfo-
> >AttributesSupported & IMAGE_ATTRIBUTE_IN_USE);
> +    Print(L"      UEFI_IMAGE                - 0x%lx\n", CurrentImageInfo-
> >AttributesSupported & IMAGE_ATTRIBUTE_UEFI_IMAGE);
> +    Print(L"    AttributesSetting           - 0x%lx\n", CurrentImageInfo-
> >AttributesSetting);
> +    Print(L"      IMAGE_UPDATABLE           - 0x%lx\n", CurrentImageInfo-
> >AttributesSetting & IMAGE_ATTRIBUTE_IMAGE_UPDATABLE);
> +    Print(L"      RESET_REQUIRED            - 0x%lx\n", CurrentImageInfo-
> >AttributesSetting & IMAGE_ATTRIBUTE_RESET_REQUIRED);
> +    Print(L"      AUTHENTICATION_REQUIRED   - 0x%lx\n", CurrentImageInfo-
> >AttributesSetting & IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);
> +    Print(L"      IN_USE                    - 0x%lx\n", CurrentImageInfo-
> >AttributesSetting & IMAGE_ATTRIBUTE_IN_USE);
> +    Print(L"      UEFI_IMAGE                - 0x%lx\n", CurrentImageInfo-
> >AttributesSetting & IMAGE_ATTRIBUTE_UEFI_IMAGE);
> +    Print(L"    Compatibilities             - 0x%lx\n", CurrentImageInfo-
> >Compatibilities);
> +    Print(L"      COMPATIB_CHECK_SUPPORTED  - 0x%lx\n", CurrentImageInfo-
> >Compatibilities & IMAGE_COMPATIBILITY_CHECK_SUPPORTED);
> +    if (DescriptorVersion > 1) {
> +      Print(L"    LowestSupportedImageVersion - 0x%x\n", CurrentImageInfo-
> >LowestSupportedImageVersion);
> +      if (DescriptorVersion > 2) {
> +        Print(L"    LastAttemptVersion          - 0x%x\n", CurrentImageInfo-
> >LastAttemptVersion);
> +        Print(L"    LastAttemptStatus           - 0x%x (%a)\n", CurrentImageInfo-
> >LastAttemptStatus, LastAttemptStatusToString(CurrentImageInfo->LastAttemptStatus));
> +        Print(L"    HardwareInstance            - 0x%lx\n", CurrentImageInfo-
> >HardwareInstance);
> +      }
> +    }
> +    //
> +    // Use DescriptorSize to move ImageInfo Pointer to stay compatible with different
> ImageInfo version
> +    //
> +    CurrentImageInfo = (EFI_FIRMWARE_IMAGE_DESCRIPTOR *)((UINT8 *)CurrentImageInfo +
> DescriptorSize);
> +  }
> +}
> +
> +/**
> +  Dump FMP package information.
> +
> +  @param PackageVersion             The version of package.
> +  @param PackageVersionName         The version name of package.
> +  @param PackageVersionNameMaxLen   The maximum length of PackageVersionName.
> +  @param AttributesSupported        Package attributes that are supported by this
> device.
> +  @param AttributesSetting          Package attributes.
> +**/
> +VOID
> +DumpFmpPackageInfo(
> +  IN UINT32                           PackageVersion,
> +  IN CHAR16                           *PackageVersionName,
> +  IN UINT32                           PackageVersionNameMaxLen,
> +  IN UINT64                           AttributesSupported,
> +  IN UINT64                           AttributesSetting
> +  )
> +{
> +  Print(L"  PackageVersion              - 0x%x\n", PackageVersion);
> +  Print(L"  PackageVersionName          - \"%s\"\n", PackageVersionName);
> +  Print(L"  PackageVersionNameMaxLen    - 0x%x\n", PackageVersionNameMaxLen);
> +  Print(L"  AttributesSupported         - 0x%lx\n", AttributesSupported);
> +  Print(L"    IMAGE_UPDATABLE           - 0x%lx\n", AttributesSupported &
> IMAGE_ATTRIBUTE_IMAGE_UPDATABLE);
> +  Print(L"    RESET_REQUIRED            - 0x%lx\n", AttributesSupported &
> IMAGE_ATTRIBUTE_RESET_REQUIRED);
> +  Print(L"    AUTHENTICATION_REQUIRED   - 0x%lx\n", AttributesSupported &
> IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);
> +  Print(L"  AttributesSetting           - 0x%lx\n", AttributesSetting);
> +  Print(L"    IMAGE_UPDATABLE           - 0x%lx\n", AttributesSetting &
> IMAGE_ATTRIBUTE_IMAGE_UPDATABLE);
> +  Print(L"    RESET_REQUIRED            - 0x%lx\n", AttributesSetting &
> IMAGE_ATTRIBUTE_RESET_REQUIRED);
> +  Print(L"    AUTHENTICATION_REQUIRED   - 0x%lx\n", AttributesSetting &
> IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);
> +}
> +
> +/**
> +  Dump FMP protocol info.
> +**/
> +VOID
> +DumpFmpData (
> +  VOID
> +  )
> +{
> +  EFI_STATUS                                    Status;
> +  EFI_FIRMWARE_MANAGEMENT_PROTOCOL              *Fmp;
> +  EFI_HANDLE                                    *HandleBuffer;
> +  UINTN                                         NumberOfHandles;
> +  UINTN                                         Index;
> +  EFI_FIRMWARE_IMAGE_DESCRIPTOR                 *FmpImageInfoBuf;
> +  UINTN                                         ImageInfoSize;
> +  UINT32                                        FmpImageInfoDescriptorVer;
> +  UINT8                                         FmpImageInfoCount;
> +  UINTN                                         DescriptorSize;
> +  UINT32                                        PackageVersion;
> +  CHAR16                                        *PackageVersionName;
> +  UINT32                                        PackageVersionNameMaxLen;
> +  UINT64                                        AttributesSupported;
> +  UINT64                                        AttributesSetting;
> +
> +  Print(L"############\n");
> +  Print(L"# FMP DATA #\n");
> +  Print(L"############\n");
> +  Status = gBS->LocateHandleBuffer (
> +                  ByProtocol,
> +                  &gEfiFirmwareManagementProtocolGuid,
> +                  NULL,
> +                  &NumberOfHandles,
> +                  &HandleBuffer
> +                  );
> +  if (EFI_ERROR(Status)) {
> +    Print(L"FMP protocol - %r\n", EFI_NOT_FOUND);
> +    return;
> +  }
> +
> +  for (Index = 0; Index < NumberOfHandles; Index++) {
> +    Status = gBS->HandleProtocol(
> +                    HandleBuffer[Index],
> +                    &gEfiFirmwareManagementProtocolGuid,
> +                    (VOID **)&Fmp
> +                    );
> +    if (EFI_ERROR(Status)) {
> +      continue;
> +    }
> +
> +    ImageInfoSize = 0;
> +    Status = Fmp->GetImageInfo (
> +                    Fmp,
> +                    &ImageInfoSize,
> +                    NULL,
> +                    NULL,
> +                    NULL,
> +                    NULL,
> +                    NULL,
> +                    NULL
> +                    );
> +    if (Status != EFI_BUFFER_TOO_SMALL) {
> +      continue;
> +    }
> +
> +    FmpImageInfoBuf = NULL;
> +    FmpImageInfoBuf = AllocateZeroPool (ImageInfoSize);
> +    if (FmpImageInfoBuf == NULL) {
> +      Status = EFI_OUT_OF_RESOURCES;
> +      goto EXIT;
> +    }
> +
> +    PackageVersionName = NULL;
> +    Status = Fmp->GetImageInfo (
> +                    Fmp,
> +                    &ImageInfoSize,               // ImageInfoSize
> +                    FmpImageInfoBuf,              // ImageInfo
> +                    &FmpImageInfoDescriptorVer,   // DescriptorVersion
> +                    &FmpImageInfoCount,           // DescriptorCount
> +                    &DescriptorSize,              // DescriptorSize
> +                    &PackageVersion,              // PackageVersion
> +                    &PackageVersionName           // PackageVersionName
> +                    );
> +
> +    //
> +    // If FMP GetInformation interface failed, skip this resource
> +    //
> +    if (EFI_ERROR(Status)) {
> +      Print(L"FMP (%d) ImageInfo - %r\n", Index, Status);
> +      FreePool(FmpImageInfoBuf);
> +      continue;
> +    }
> +
> +    Print(L"FMP (%d) ImageInfo:\n", Index);
> +    DumpFmpImageInfo(
> +      ImageInfoSize,               // ImageInfoSize
> +      FmpImageInfoBuf,             // ImageInfo
> +      FmpImageInfoDescriptorVer,   // DescriptorVersion
> +      FmpImageInfoCount,           // DescriptorCount
> +      DescriptorSize,              // DescriptorSize
> +      PackageVersion,              // PackageVersion
> +      PackageVersionName           // PackageVersionName
> +      );
> +
> +    if (PackageVersionName != NULL) {
> +      FreePool(PackageVersionName);
> +    }
> +    FreePool(FmpImageInfoBuf);
> +
> +    //
> +    // Get package info
> +    //
> +    PackageVersionName = NULL;
> +    Status = Fmp->GetPackageInfo (
> +                    Fmp,
> +                    &PackageVersion,              // PackageVersion
> +                    &PackageVersionName,          // PackageVersionName
> +                    &PackageVersionNameMaxLen,    // PackageVersionNameMaxLen
> +                    &AttributesSupported,         // AttributesSupported
> +                    &AttributesSetting            // AttributesSetting
> +                    );
> +    if (EFI_ERROR(Status)) {
> +      Print(L"FMP (%d) PackageInfo - %r\n", Index, Status);
> +    } else {
> +      Print(L"FMP (%d) ImageInfo:\n", Index);
> +      DumpFmpPackageInfo(
> +        PackageVersion,              // PackageVersion
> +        PackageVersionName,          // PackageVersionName
> +        PackageVersionNameMaxLen,    // PackageVersionNameMaxLen
> +        AttributesSupported,         // AttributesSupported
> +        AttributesSetting            // AttributesSetting
> +        );
> +
> +      if (PackageVersionName != NULL) {
> +        FreePool(PackageVersionName);
> +      }
> +    }
> +  }
> +  Print(L"\n");
> +
> +EXIT:
> +  FreePool(HandleBuffer);
> +}
> --
> 2.7.4.windows.1
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>
https://lists.01.org/mailman/listinfo/edk2-devel

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

* Re: [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application.
  2016-10-03 18:35               ` Rothman, Michael A
@ 2016-10-03 20:38                 ` Carsey, Jaben
  2016-10-11  8:08                   ` Ni, Ruiyu
  0 siblings, 1 reply; 83+ messages in thread
From: Carsey, Jaben @ 2016-10-03 20:38 UTC (permalink / raw)
  To: Rothman, Michael A, Ni, Ruiyu, Yao, Jiewen, Kinney, Michael D,
	edk2-devel@lists.01.org
  Cc: Tian, Feng, Zhang, Chao B, Gao, Liming, Zeng, Star, Carsey, Jaben

I don’t think that is what I meant.  It’s a string and a length, not a structure.

I mean clarify the following:

1)      Is the name of the binary itself in the LoadOptions string as the first option or not there at all?

2)      Then clarify that all Parameters are space delimited.

From: Rothman, Michael A
Sent: Monday, October 03, 2016 11:36 AM
To: Carsey, Jaben <jaben.carsey@intel.com>; Ni, Ruiyu <ruiyu.ni@intel.com>; Yao, Jiewen <jiewen.yao@intel.com>; Kinney, Michael D <michael.d.kinney@intel.com>; edk2-devel@lists.01.org
Cc: Tian, Feng <feng.tian@intel.com>; Zhang, Chao B <chao.b.zhang@intel.com>; Gao, Liming <liming.gao@intel.com>; Zeng, Star <star.zeng@intel.com>; Rothman, Michael A <michael.a.rothman@intel.com>
Subject: RE: [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application.
Importance: High

You mean update the LoadOptions reference to refer to the EFI_LOAD_OPTION structure? Because that’s in essence what it means.

Thanks,
Mike Rothman
(迈克 罗斯曼 / माइकल रोथ्मेन् / Михаил Ротман / משה רוטמן)
רועה עיקרי של חתולים

From: Carsey, Jaben
Sent: Friday, September 30, 2016 8:31 AM
To: Ni, Ruiyu <ruiyu.ni@intel.com<mailto:ruiyu.ni@intel.com>>; Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>; edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>; Rothman, Michael A <michael.a.rothman@intel.com<mailto:michael.a.rothman@intel.com>>
Cc: Tian, Feng <feng.tian@intel.com<mailto:feng.tian@intel.com>>; Zhang, Chao B <chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com>>; Gao, Liming <liming.gao@intel.com<mailto:liming.gao@intel.com>>; Zeng, Star <star.zeng@intel.com<mailto:star.zeng@intel.com>>; Carsey, Jaben <jaben.carsey@intel.com<mailto:jaben.carsey@intel.com>>
Subject: RE: [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application.

Mike Rothman,

Can we get LoadOptions and LoadOptionsSize clarified in the UEFI Spec?  This seems like a simple clarification and I would argue its needed.  The UEFI Shell is not the only producer of this protocol.  BDS launches things (like the UEFI Shell itself) and the shell already consumes it for itself (and it works).  I think it just needs clarification so people can depend on the current implementation not changing.

-Jaben

From: Ni, Ruiyu
Sent: Thursday, September 29, 2016 9:13 PM
To: Carsey, Jaben <jaben.carsey@intel.com<mailto:jaben.carsey@intel.com>>; Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>; edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>
Cc: Tian, Feng <feng.tian@intel.com<mailto:feng.tian@intel.com>>; Zhang, Chao B <chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com>>; Gao, Liming <liming.gao@intel.com<mailto:liming.gao@intel.com>>; Zeng, Star <star.zeng@intel.com<mailto:star.zeng@intel.com>>
Subject: RE: [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application.
Importance: High

Supposing user inputs “CapsuleApp.efi Parameter1 Parameter2”.
There is no spec to define what the LoadOption should equal to.
If there is another UEFI Shell implementation, it could interpret the command line then sets only “Parameter1 Parameter2” into LoadOption, or sets “CapsuleApp.efi\tParameter1\tParameter2” to LoadOption, or sets “[Shell]\tCapsuleApp.efi\tParameter1\tParameter2” to LoadOption.
Because it“produces” such LoadOption, it knows how to “consume”/parse it to get the ARGVs.

So I suggest we put the CapsuleApp in ShellPkg and let it use the ShellParameter protocol.

Regards,
Ray

From: Carsey, Jaben
Sent: Friday, September 30, 2016 3:11 AM
To: Ni, Ruiyu <ruiyu.ni@intel.com<mailto:ruiyu.ni@intel.com>>; Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>; edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>
Cc: Tian, Feng <feng.tian@intel.com<mailto:feng.tian@intel.com>>; Zhang, Chao B <chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com>>; Gao, Liming <liming.gao@intel.com<mailto:liming.gao@intel.com>>; Zeng, Star <star.zeng@intel.com<mailto:star.zeng@intel.com>>; Carsey, Jaben <jaben.carsey@intel.com<mailto:jaben.carsey@intel.com>>
Subject: RE: [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application.

I am confused.

Why is LoadOption and LoadOptionSize not working?  This is specified as part of UEFI Spec (Note: Not UEFI Shell Spec) as a standard way to pass parameters to UEFI appliations.  I think this should work (although it is more work than just examining argc/argv).

-Jaben

From: Ni, Ruiyu
Sent: Wednesday, September 28, 2016 11:40 PM
To: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>; edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>
Cc: Tian, Feng <feng.tian@intel.com<mailto:feng.tian@intel.com>>; Zhang, Chao B <chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com>>; Gao, Liming <liming.gao@intel.com<mailto:liming.gao@intel.com>>; Zeng, Star <star.zeng@intel.com<mailto:star.zeng@intel.com>>; Carsey, Jaben <jaben.carsey@intel.com<mailto:jaben.carsey@intel.com>>
Subject: RE: [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application.
Importance: High

Jiewen,
The way CapsuleApp extracts the ARGV assumes UEFI Shell encodes the parameters using a certain way. But the parameter encoding way is not described in the Shell spec.
Maybe we can put the CapsuleApp in ShellPkg, then let it directly use ShellParameter protocol to get the ARGV.

Copying Jaben.

Regards,
Ray

From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of Yao, Jiewen
Sent: Thursday, September 29, 2016 10:37 AM
To: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>; edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>
Cc: Tian, Feng <feng.tian@intel.com<mailto:feng.tian@intel.com>>; Zhang, Chao B <chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com>>; Gao, Liming <liming.gao@intel.com<mailto:liming.gao@intel.com>>; Zeng, Star <star.zeng@intel.com<mailto:star.zeng@intel.com>>
Subject: Re: [edk2] [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application.

Right. CapsuleOnDisk is not supported in BIOS yet.
I will remove it in CapsuleApp.

CapsuleApp just works as an agent to pass capsule to CapsuleDxeRuntime driver.
So it is checked by CapsuleDxeRuntime, not CapsuleApp.

Thank you
Yao Jiewen

From: Kinney, Michael D
Sent: Thursday, September 29, 2016 9:06 AM
To: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>; Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>
Cc: Tian, Feng <feng.tian@intel.com<mailto:feng.tian@intel.com>>; Zeng, Star <star.zeng@intel.com<mailto:star.zeng@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: [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application.

Jiewen,

Does the capsule on disk feature provided by this app work?

I tried it with the QuarkPlatformPkg capsule and I can get
The app to copy the capsule to an EFI System Partition, but
The logic after that point looks incomplete.

Also, if I clear the Persist and Reset flags on the capsule,
the immediate processing of the capsule does not work.

Is there any FW code that will look for capsules on disk?

If there are incomplete features in CapsuleApp, then I think
we should remove them.

Mike

> -----Original Message-----
> From: Yao, Jiewen
> Sent: Tuesday, September 20, 2016 11:45 PM
> To: edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org%3cmailto:edk2-devel@lists.01.org>>
> Cc: Tian, Feng <feng.tian@intel.com<mailto:feng.tian@intel.com<mailto:feng.tian@intel.com%3cmailto:feng.tian@intel.com>>>; Zeng, Star <star.zeng@intel.com<mailto:star.zeng@intel.com<mailto:star.zeng@intel.com%3cmailto:star.zeng@intel.com>>>; Kinney, Michael
> D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com%3cmailto:michael.d.kinney@intel.com>>>; Gao, Liming <liming.gao@intel.com<mailto:liming.gao@intel.com<mailto:liming.gao@intel.com%3cmailto:liming.gao@intel.com>>>; Zhang, Chao B
> <chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com%3cmailto:chao.b.zhang@intel.com>>>
> Subject: [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application.
>
> This CapsuleApp can help perform capsule update in UEFI shell environment.
> It can also dump capsule information, capsule status variable, ESRT and FMP.
>
> Cc: Feng Tian <feng.tian@intel.com<mailto:feng.tian@intel.com<mailto:feng.tian@intel.com%3cmailto:feng.tian@intel.com>>>
> Cc: Star Zeng <star.zeng@intel.com<mailto:star.zeng@intel.com<mailto:star.zeng@intel.com%3cmailto:star.zeng@intel.com>>>
> Cc: Michael D Kinney <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com%3cmailto:michael.d.kinney@intel.com>>>
> Cc: Liming Gao <liming.gao@intel.com<mailto:liming.gao@intel.com<mailto:liming.gao@intel.com%3cmailto:liming.gao@intel.com>>>
> Cc: Chao Zhang <chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com%3cmailto:chao.b.zhang@intel.com>>>
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Jiewen Yao <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com<mailto:jiewen.yao@intel.com%3cmailto:jiewen.yao@intel.com>>>
> ---
>  MdeModulePkg/Application/CapsuleApp/AppSupport.c        |  480 +++++++++
>  MdeModulePkg/Application/CapsuleApp/CapsuleApp.c        | 1047 ++++++++++++++++++++
>  MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf      |   71 ++
>  MdeModulePkg/Application/CapsuleApp/CapsuleApp.uni      |   22 +
>  MdeModulePkg/Application/CapsuleApp/CapsuleAppExtra.uni |   19 +
>  MdeModulePkg/Application/CapsuleApp/CapsuleDump.c       |  840 ++++++++++++++++
>  6 files changed, 2479 insertions(+)
>
> diff --git a/MdeModulePkg/Application/CapsuleApp/AppSupport.c
> b/MdeModulePkg/Application/CapsuleApp/AppSupport.c
> new file mode 100644
> index 0000000..365067d
> --- /dev/null
> +++ b/MdeModulePkg/Application/CapsuleApp/AppSupport.c
> @@ -0,0 +1,480 @@
> +/** @file
> +  A shell application that triggers capsule update process.
> +
> +  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the BSD License
> +  which accompanies this distribution.  The full text of the license may be found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +
> +**/
> +
> +#include <Uefi.h>
> +#include <Library/BaseLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/UefiRuntimeServicesTableLib.h>
> +#include <Library/UefiLib.h>
> +#include <Library/PrintLib.h>
> +#include <Protocol/LoadedImage.h>
> +#include <Protocol/SimpleFileSystem.h>
> +#include <Guid/FileInfo.h>
> +#include <Guid/Gpt.h>
> +
> +#define MAX_ARG_NUM     11
> +
> +UINTN  Argc = 0;
> +CHAR16 *Argv[MAX_ARG_NUM];
> +CHAR16 *ArgBuffer;
> +
> +/**
> +
> +  This function parse application ARG.
> +
> +  @return Status
> +**/
> +EFI_STATUS
> +GetArg (
> +  VOID
> +  )
> +{
> +  UINT8                         *Data;
> +  UINTN                         DataSize;
> +  CHAR16                        *Index;
> +  CHAR16                        *End;
> +  CHAR16                        *DIndex;
> +  EFI_STATUS                    Status;
> +  EFI_LOADED_IMAGE_PROTOCOL     *LoadedImage;
> +
> +  Status = gBS->HandleProtocol (
> +                  gImageHandle,
> +                  &gEfiLoadedImageProtocolGuid,
> +                  (VOID**)&LoadedImage
> +                  );
> +  if (EFI_ERROR(Status)) {
> +    return Status;
> +  }
> +
> +  Data = LoadedImage->LoadOptions;
> +  DataSize = LoadedImage->LoadOptionsSize;
> +
> +  End = (CHAR16*)(UINTN)(Data + DataSize);
> +  Status = gBS->AllocatePool (EfiBootServicesData, DataSize, (VOID **)&ArgBuffer);
> +  ASSERT_EFI_ERROR (Status);
> +  DIndex = ArgBuffer;
> +  Argv[Argc++] = ArgBuffer;
> +  for (Index = (CHAR16*)Data; Index < End; ) {
> +    if (*Index == L' ') {
> +      *DIndex = L'\0';
> +      if (Argc >= MAX_ARG_NUM) {
> +        return EFI_UNSUPPORTED;
> +      }
> +      Argv[Argc++] = (++ DIndex);
> +      while(*Index == L' ') {
> +        Index ++;
> +      }
> +    }
> +    (*(DIndex ++)) = (*(Index ++));
> +  }
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Clear APP ARG.
> +**/
> +VOID
> +CleanArg (
> +  VOID
> +  )
> +{
> +  FreePool (Argv[0]);
> +}
> +
> +/**
> +  Return File System Volume containing this shell application.
> +
> +  @return File System Volume containing this shell application.
> +**/
> +EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *
> +GetMyVol (
> +  VOID
> +  )
> +{
> +  EFI_STATUS                        Status;
> +  EFI_LOADED_IMAGE_PROTOCOL         *LoadedImage;
> +  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Vol;
> +
> +  Status = gBS->HandleProtocol (
> +                  gImageHandle,
> +                  &gEfiLoadedImageProtocolGuid,
> +                  (VOID **)&LoadedImage
> +                  );
> +  ASSERT_EFI_ERROR (Status);
> +
> +  Status = gBS->HandleProtocol (
> +                  LoadedImage->DeviceHandle,
> +                  &gEfiSimpleFileSystemProtocolGuid,
> +                  (VOID **)&Vol
> +                  );
> +  if (!EFI_ERROR (Status)) {
> +    return Vol;
> +  }
> +
> +  return NULL;
> +}
> +
> +/**
> +  Read a file from this volume.
> +
> +  @param Vol             File System Volume
> +  @param FileName        The file to be read.
> +  @param BufferSize      The file buffer size
> +  @param Buffer          The file buffer
> +
> +  @retval EFI_SUCCESS    Read file successfully
> +  @retval EFI_NOT_FOUND  File not found
> +**/
> +EFI_STATUS
> +ReadFileFromVol (
> +  IN  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Vol,
> +  IN  CHAR16                            *FileName,
> +  OUT UINTN                             *BufferSize,
> +  OUT VOID                              **Buffer
> +  )
> +{
> +  EFI_STATUS                        Status;
> +  EFI_FILE_HANDLE                   RootDir;
> +  EFI_FILE_HANDLE                   Handle;
> +  UINTN                             FileInfoSize;
> +  EFI_FILE_INFO                     *FileInfo;
> +  UINTN                             TempBufferSize;
> +  VOID                              *TempBuffer;
> +
> +  //
> +  // Open the root directory
> +  //
> +  Status = Vol->OpenVolume (Vol, &RootDir);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  //
> +  // Open the file
> +  //
> +  Status = RootDir->Open (
> +                      RootDir,
> +                      &Handle,
> +                      FileName,
> +                      EFI_FILE_MODE_READ,
> +                      0
> +                      );
> +  if (EFI_ERROR (Status)) {
> +    RootDir->Close (RootDir);
> +    return Status;
> +  }
> +
> +  RootDir->Close (RootDir);
> +
> +  //
> +  // Get the file information
> +  //
> +  FileInfoSize = sizeof(EFI_FILE_INFO) + 1024;
> +
> +  FileInfo = AllocateZeroPool (FileInfoSize);
> +  if (FileInfo == NULL) {
> +    Handle->Close (Handle);
> +    return Status;
> +  }
> +
> +  Status = Handle->GetInfo (
> +                     Handle,
> +                     &gEfiFileInfoGuid,
> +                     &FileInfoSize,
> +                     FileInfo
> +                     );
> +  if (EFI_ERROR (Status)) {
> +    Handle->Close (Handle);
> +    gBS->FreePool (FileInfo);
> +    return Status;
> +  }
> +
> +  //
> +  // Allocate buffer for the file data. The last CHAR16 is for L'\0'
> +  //
> +  TempBufferSize = (UINTN) FileInfo->FileSize + sizeof(CHAR16);
> +  TempBuffer = AllocateZeroPool (TempBufferSize);
> +  if (TempBuffer == NULL) {
> +    Handle->Close (Handle);
> +    gBS->FreePool (FileInfo);
> +    return Status;
> +  }
> +
> +  gBS->FreePool (FileInfo);
> +
> +  //
> +  // Read the file data to the buffer
> +  //
> +  Status = Handle->Read (
> +                     Handle,
> +                     &TempBufferSize,
> +                     TempBuffer
> +                     );
> +  if (EFI_ERROR (Status)) {
> +    Handle->Close (Handle);
> +    gBS->FreePool (TempBuffer);
> +    return Status;
> +  }
> +
> +  Handle->Close (Handle);
> +
> +  *BufferSize = TempBufferSize;
> +  *Buffer     = TempBuffer;
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Read a file.
> +  If ScanFs is FLASE, it will use this Vol as default Fs.
> +  If ScanFs is TRUE, it will scan all FS and check the file.
> +    If there is only one file match the name, it will be read.
> +    If there is more than one file match the name, it will return Error.
> +
> +  @param ThisVol         File System Volume
> +  @param FileName        The file to be read.
> +  @param BufferSize      The file buffer size
> +  @param Buffer          The file buffer
> +  @param ScanFs          Need Scan all FS
> +
> +  @retval EFI_SUCCESS    Read file successfully
> +  @retval EFI_NOT_FOUND  File not found
> +  @retval EFI_NO_MAPPING There is duplicated files found
> +**/
> +EFI_STATUS
> +ReadFileToBufferEx (
> +  IN OUT EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   **ThisVol,
> +  IN  CHAR16                               *FileName,
> +  OUT UINTN                                *BufferSize,
> +  OUT VOID                                 **Buffer,
> +  IN  BOOLEAN                              ScanFs
> +  )
> +{
> +  EFI_STATUS                        Status;
> +  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Vol;
> +  UINTN                             TempBufferSize;
> +  VOID                              *TempBuffer;
> +  UINTN                             NoHandles;
> +  EFI_HANDLE                        *HandleBuffer;
> +  UINTN                             Index;
> +
> +  //
> +  // Check parameters
> +  //
> +  if ((FileName == NULL) || (Buffer == NULL) || (ThisVol == NULL)) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  //
> +  // not scan fs
> +  //
> +  if (!ScanFs) {
> +    if (*ThisVol == NULL) {
> +      *ThisVol = GetMyVol ();
> +      if (*ThisVol == NULL) {
> +        return EFI_INVALID_PARAMETER;
> +      }
> +    }
> +    //
> +    // Read file directly from Vol
> +    //
> +    return ReadFileFromVol (*ThisVol, FileName, BufferSize, Buffer);
> +  }
> +
> +  //
> +  // need scan fs
> +  //
> +
> +  //
> +  // Get all Vol handle
> +  //
> +  Status = gBS->LocateHandleBuffer (
> +                   ByProtocol,
> +                   &gEfiSimpleFileSystemProtocolGuid,
> +                   NULL,
> +                   &NoHandles,
> +                   &HandleBuffer
> +                   );
> +  if (EFI_ERROR (Status) && (NoHandles == 0)) {
> +    return EFI_NOT_FOUND;
> +  }
> +
> +  //
> +  // Walk through each Vol
> +  //
> +  *ThisVol = NULL;
> +  *BufferSize = 0;
> +  *Buffer     = NULL;
> +  for (Index = 0; Index < NoHandles; Index++) {
> +    Status = gBS->HandleProtocol (
> +                    HandleBuffer[Index],
> +                    &gEfiSimpleFileSystemProtocolGuid,
> +                    (VOID **)&Vol
> +                    );
> +    if (EFI_ERROR(Status)) {
> +      continue;
> +    }
> +
> +    Status = ReadFileFromVol (Vol, FileName, &TempBufferSize, &TempBuffer);
> +    if (!EFI_ERROR (Status)) {
> +      //
> +      // Read file OK, check duplication
> +      //
> +      if (*ThisVol != NULL) {
> +        //
> +        // Find the duplicated file
> +        //
> +        gBS->FreePool (TempBuffer);
> +        gBS->FreePool (*Buffer);
> +        Print (L"Duplicated FileName found!\n");
> +        return EFI_NO_MAPPING;
> +      } else {
> +        //
> +        // Record value
> +        //
> +        *ThisVol = Vol;
> +        *BufferSize = TempBufferSize;
> +        *Buffer     = TempBuffer;
> +      }
> +    }
> +  }
> +
> +  //
> +  // Scan Fs done
> +  //
> +  if (*ThisVol == NULL) {
> +    return EFI_NOT_FOUND;
> +  }
> +
> +  //
> +  // Done
> +  //
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Read a file.
> +
> +  @param FileName        The file to be read.
> +  @param BufferSize      The file buffer size
> +  @param Buffer          The file buffer
> +
> +  @retval EFI_SUCCESS    Read file successfully
> +  @retval EFI_NOT_FOUND  File not found
> +**/
> +EFI_STATUS
> +ReadFileToBuffer (
> +  IN  CHAR16                               *FileName,
> +  OUT UINTN                                *BufferSize,
> +  OUT VOID                                 **Buffer
> +  )
> +{
> +  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Vol;
> +  Vol = NULL;
> +  return ReadFileToBufferEx(&Vol, FileName, BufferSize, Buffer, FALSE);
> +}
> +
> +/**
> +  Write a file.
> +
> +  @param FileName        The file to be written.
> +  @param BufferSize      The file buffer size
> +  @param Buffer          The file buffer
> +
> +  @retval EFI_SUCCESS    Write file successfully
> +**/
> +EFI_STATUS
> +WriteFileFromBuffer(
> +  IN  CHAR16                               *FileName,
> +  IN  UINTN                                BufferSize,
> +  IN  VOID                                 *Buffer
> +  )
> +{
> +  EFI_STATUS                        Status;
> +  EFI_FILE_HANDLE                   RootDir;
> +  EFI_FILE_HANDLE                   Handle;
> +  UINTN                             TempBufferSize;
> +  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Vol;
> +
> +  Vol = GetMyVol();
> +
> +  //
> +  // Open the root directory
> +  //
> +  Status = Vol->OpenVolume (Vol, &RootDir);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  //
> +  // Open the file
> +  //
> +  Status = RootDir->Open (
> +                      RootDir,
> +                      &Handle,
> +                      FileName,
> +                      EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE| EFI_FILE_MODE_CREATE,
> +                      0
> +                      );
> +  if (EFI_ERROR (Status)) {
> +    RootDir->Close (RootDir);
> +    return Status;
> +  }
> +
> +  //
> +  // Delete file
> +  //
> +  Status = Handle->Delete(Handle);
> +  if (EFI_ERROR(Status)) {
> +    return Status;
> +  }
> +
> +  //
> +  // Open the file again
> +  //
> +  Status = RootDir->Open (
> +                      RootDir,
> +                      &Handle,
> +                      FileName,
> +                      EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE| EFI_FILE_MODE_CREATE,
> +                      0
> +                      );
> +  if (EFI_ERROR (Status)) {
> +    RootDir->Close (RootDir);
> +    return Status;
> +  }
> +
> +  RootDir->Close (RootDir);
> +
> +  //
> +  // Write the file data from the buffer
> +  //
> +  TempBufferSize = BufferSize;
> +  Status = Handle->Write (
> +                     Handle,
> +                     &TempBufferSize,
> +                     Buffer
> +                     );
> +  if (EFI_ERROR (Status)) {
> +    Handle->Close (Handle);
> +    return Status;
> +  }
> +
> +  Handle->Close (Handle);
> +
> +  return EFI_SUCCESS;
> +}
> +
> diff --git a/MdeModulePkg/Application/CapsuleApp/CapsuleApp.c
> b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.c
> new file mode 100644
> index 0000000..0a28557
> --- /dev/null
> +++ b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.c
> @@ -0,0 +1,1047 @@
> +/** @file
> +  A shell application that triggers capsule update process.
> +
> +  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the BSD License
> +  which accompanies this distribution.  The full text of the license may be found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +
> +**/
> +
> +#include <Uefi.h>
> +#include <Library/BaseLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/UefiRuntimeServicesTableLib.h>
> +#include <Library/UefiLib.h>
> +#include <Library/PrintLib.h>
> +#include <Protocol/LoadedImage.h>
> +#include <Protocol/SimpleFileSystem.h>
> +#include <Protocol/GraphicsOutput.h>
> +#include <Guid/FileInfo.h>
> +#include <Guid/Gpt.h>
> +#include <Guid/GlobalVariable.h>
> +#include <Guid/CapsuleReport.h>
> +#include <Guid/SystemResourceTable.h>
> +#include <Guid/FmpCapsule.h>
> +#include <IndustryStandard/WindowsUxCapsule.h>
> +
> +#define CAPSULE_HEADER_SIZE  0x20
> +
> +#define NESTED_CAPSULE_HEADER_SIZE  SIZE_4KB
> +#define SYSTEM_FIRMWARE_FLAG 0x50000
> +#define DEVICE_FIRMWARE_FLAG 0x78010
> +
> +#define EFI_CAPSULE_FROM_FILE_DIR                           L"\\EFI\\UpdateCapsule\\<file:///\\EFI\UpdateCapsule\><file:///\\EFI\UpdateCapsule\%3cfile:\EFI\UpdateCapsule\%3e>"
> +#define EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED  0x0000000000000004
> +
> +#define MAJOR_VERSION   1
> +#define MINOR_VERSION   0
> +
> +#define MAX_ARG_NUM     11
> +#define MAX_CAPSULE_NUM (MAX_ARG_NUM - 1)
> +
> +extern UINTN  Argc;
> +extern CHAR16 *Argv[];
> +
> +//
> +// Define how many block descriptors we want to test with.
> +//
> +UINTN  NumberOfDescriptors = 1;
> +UINTN  CapsuleFirstIndex;
> +UINTN  CapsuleLastIndex;
> +
> +/**
> +  Dump capsule information
> +
> +  @retval EFI_SUCCESS            The capsule information is dumped.
> +  @retval EFI_UNSUPPORTED        Input parameter is not valid.
> +**/
> +EFI_STATUS
> +DumpCapsule(
> +  VOID
> +  );
> +
> +/**
> +  Dump capsule status variable.
> +
> +  @retval EFI_SUCCESS            The capsule status variable is dumped.
> +  @retval EFI_UNSUPPORTED        Input parameter is not valid.
> +**/
> +EFI_STATUS
> +DmpCapsuleStatusVariable(
> +  VOID
> +  );
> +
> +/**
> +  Dump FMP protocol info.
> +**/
> +VOID
> +DumpFmpData(
> +  VOID
> +  );
> +
> +/**
> +  Dump ESRT info.
> +**/
> +VOID
> +DumpEsrtData(
> +  VOID
> +  );
> +
> +/**
> +  Read a file.
> +
> +  @param FileName        The file to be read.
> +  @param BufferSize      The file buffer size
> +  @param Buffer          The file buffer
> +
> +  @retval EFI_SUCCESS    Read file successfully
> +  @retval EFI_NOT_FOUND  File not found
> +**/
> +EFI_STATUS
> +ReadFileToBuffer(
> +  IN  CHAR16                               *FileName,
> +  OUT UINTN                                *BufferSize,
> +  OUT VOID                                 **Buffer
> +  );
> +
> +/**
> +  Write a file.
> +
> +  @param FileName        The file to be written.
> +  @param BufferSize      The file buffer size
> +  @param Buffer          The file buffer
> +
> +  @retval EFI_SUCCESS    Write file successfully
> +**/
> +EFI_STATUS
> +WriteFileFromBuffer(
> +  IN  CHAR16                               *FileName,
> +  IN  UINTN                                BufferSize,
> +  IN  VOID                                 *Buffer
> +  );
> +
> +/**
> +
> +  This function parse application ARG.
> +
> +  @return Status
> +**/
> +EFI_STATUS
> +GetArg (
> +  VOID
> +  );
> +
> +/**
> +  Clear APP ARG.
> +**/
> +VOID
> +CleanArg (
> +  VOID
> +  );
> +
> +/**
> +  Create UX capsule.
> +
> +  @retval EFI_SUCCESS            The capsule header is appended.
> +  @retval EFI_UNSUPPORTED        Input parameter is not valid.
> +  @retval EFI_OUT_OF_RESOURCES   No enough resource to create UX capsule.
> +**/
> +EFI_STATUS
> +CreateBmpFmp(
> +  VOID
> +  )
> +{
> +  CHAR16                                        *OutputCapsuleName;
> +  VOID                                          *BmpBuffer;
> +  UINTN                                         FileSize;
> +  CHAR16                                        *BmpName;
> +  UINT8                                         *FullCapsuleBuffer;
> +  UINTN                                         FullCapsuleBufferSize;
> +  EFI_DISPLAY_CAPSULE                           *DisplayCapsule;
> +  EFI_STATUS                                    Status;
> +  EFI_GRAPHICS_OUTPUT_PROTOCOL                  *Gop;
> +
> +  Status = gBS->LocateProtocol(&gEfiGraphicsOutputProtocolGuid, NULL, (VOID **)&Gop);
> +  if (EFI_ERROR(Status)) {
> +    Print(L"CapsuleApp: NO GOP is found.\n");
> +    return EFI_UNSUPPORTED;
> +  }
> +  Print(L"Current GOP: Mode - %d, ", Gop->Mode->Mode);
> +  Print(L"HorizontalResolution - %d, ", Gop->Mode->Info->HorizontalResolution);
> +  Print(L"VerticalResolution - %d\n", Gop->Mode->Info->VerticalResolution);
> +  // HorizontalResolution >= BMP_IMAGE_HEADER.PixelWidth
> +  // VerticalResolution   >= BMP_IMAGE_HEADER.PixelHeight
> +
> +  if (Argc != 5) {
> +    Print(L"CapsuleApp: Invalid Parameter.\n");
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  if (StrCmp(Argv[3], L"-O") != 0) {
> +    Print(L"CapsuleApp: NO output capsule name.\n");
> +    return EFI_UNSUPPORTED;
> +  }
> +  OutputCapsuleName = Argv[4];
> +
> +  BmpBuffer = NULL;
> +  FileSize = 0;
> +  FullCapsuleBuffer = NULL;
> +
> +  BmpName = Argv[2];
> +  Status = ReadFileToBuffer(BmpName, &FileSize, &BmpBuffer);
> +  if (EFI_ERROR(Status)) {
> +    Print(L"CapsuleApp: BMP image (%s) is not found.\n", BmpName);
> +    goto Done;
> +  }
> +
> +  FullCapsuleBufferSize = sizeof(EFI_DISPLAY_CAPSULE) + FileSize;
> +  FullCapsuleBuffer = AllocatePool(FullCapsuleBufferSize);
> +  if (FullCapsuleBuffer == NULL) {
> +    Print(L"CapsuleApp: Capsule Buffer size (0x%x) too big.\n",
> FullCapsuleBufferSize);
> +    Status = EFI_OUT_OF_RESOURCES;
> +    goto Done;
> +  }
> +
> +  DisplayCapsule = (EFI_DISPLAY_CAPSULE *)FullCapsuleBuffer;
> +  CopyGuid(&DisplayCapsule->CapsuleHeader.CapsuleGuid, &gWindowsUxCapsuleGuid);
> +  DisplayCapsule->CapsuleHeader.HeaderSize = sizeof(DisplayCapsule->CapsuleHeader);
> +  DisplayCapsule->CapsuleHeader.Flags = CAPSULE_FLAGS_PERSIST_ACROSS_RESET;
> +  DisplayCapsule->CapsuleHeader.CapsuleImageSize = (UINT32)FullCapsuleBufferSize;
> +
> +  DisplayCapsule->ImagePayload.Version = 1;
> +  DisplayCapsule->ImagePayload.Checksum = 0;
> +  DisplayCapsule->ImagePayload.ImageType = 0; // BMP
> +  DisplayCapsule->ImagePayload.Reserved = 0;
> +  DisplayCapsule->ImagePayload.Mode = Gop->Mode->Mode;
> +  DisplayCapsule->ImagePayload.OffsetX = 0;
> +  DisplayCapsule->ImagePayload.OffsetY = 0;
> +
> +  CopyMem((DisplayCapsule + 1), BmpBuffer, FileSize);
> +
> +  DisplayCapsule->ImagePayload.Checksum = CalculateCheckSum8(FullCapsuleBuffer,
> FullCapsuleBufferSize);
> +
> +  Status = WriteFileFromBuffer(OutputCapsuleName, FullCapsuleBufferSize,
> FullCapsuleBuffer);
> +  Print(L"CapsuleApp: Write %s %r\n", OutputCapsuleName, Status);
> +
> +Done:
> +  if (BmpBuffer != NULL) {
> +    FreePool(BmpBuffer);
> +  }
> +
> +  if (FullCapsuleBuffer != NULL) {
> +    FreePool(FullCapsuleBuffer);
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  Get ImageTypeId in the FMP capsule header.
> +
> +  @param CapsuleHeader  The FMP capsule image header.
> +
> +  @return ImageTypeId
> +**/
> +EFI_GUID *
> +GetCapsuleImageTypeId(
> +  IN EFI_CAPSULE_HEADER                            *CapsuleHeader
> +  )
> +{
> +  EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER       *FmpCapsuleHeader;
> +  UINT64                                       *ItemOffsetList;
> +  EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader;
> +
> +  FmpCapsuleHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *)((UINT8 *)CapsuleHeader
> + CapsuleHeader->HeaderSize);
> +  ItemOffsetList = (UINT64 *)(FmpCapsuleHeader + 1);
> +  if (FmpCapsuleHeader->PayloadItemCount == 0) {
> +    return NULL;
> +  }
> +  ImageHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *)((UINT8
> *)FmpCapsuleHeader + ItemOffsetList[FmpCapsuleHeader->EmbeddedDriverCount]);
> +  return &ImageHeader->UpdateImageTypeId;
> +}
> +
> +/**
> +  Get ESRT FwType according to ImageTypeId
> +
> +  @param  ImageTypeId   ImageTypeId of an FMP capsule.
> +
> +  @return ESRT FwType
> +**/
> +UINT32
> +GetEsrtFwType(
> +  IN  EFI_GUID                                      *ImageTypeId
> +  )
> +{
> +  EFI_STATUS                 Status;
> +  EFI_SYSTEM_RESOURCE_TABLE  *Esrt;
> +  EFI_SYSTEM_RESOURCE_ENTRY  *EsrtEntry;
> +  UINTN                      Index;
> +
> +  //
> +  // Check ESRT
> +  //
> +  Status = EfiGetSystemConfigurationTable(&gEfiSystemResourceTableGuid, (VOID
> **)&Esrt);
> +  if (!EFI_ERROR(Status)) {
> +    EsrtEntry = (VOID *)(Esrt + 1);
> +    for (Index = 0; Index < Esrt->FwResourceCount; Index++, EsrtEntry++) {
> +      if (CompareGuid(&EsrtEntry->FwClass, ImageTypeId)) {
> +        return EsrtEntry->FwType;
> +      }
> +    }
> +  }
> +
> +  return ESRT_FW_TYPE_UNKNOWN;
> +}
> +
> +/**
> +  Append a capsule header on top of current image.
> +  This function follows Windows UEFI Firmware Update Platform document.
> +
> +  @retval EFI_SUCCESS            The capsule header is appended.
> +  @retval EFI_UNSUPPORTED        Input parameter is not valid.
> +  @retval EFI_OUT_OF_RESOURCES   No enough resource to append capsule header.
> +**/
> +EFI_STATUS
> +CreateNestedFmp(
> +  VOID
> +  )
> +{
> +  CHAR16                                        *OutputCapsuleName;
> +  VOID                                          *CapsuleBuffer;
> +  UINTN                                         FileSize;
> +  CHAR16                                        *CapsuleName;
> +  UINT8                                         *FullCapsuleBuffer;
> +  UINTN                                         FullCapsuleBufferSize;
> +  EFI_CAPSULE_HEADER                            *NestedCapsuleHeader;
> +  EFI_GUID                                      *ImageTypeId;
> +  UINT32                                        FwType;
> +  EFI_STATUS                                    Status;
> +
> +  if (Argc != 5) {
> +    Print(L"CapsuleApp: Invalid Parameter.\n");
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  if (StrCmp(Argv[3], L"-O") != 0) {
> +    Print(L"CapsuleApp: NO output capsule name.\n");
> +    return EFI_UNSUPPORTED;
> +  }
> +  OutputCapsuleName = Argv[4];
> +
> +  CapsuleBuffer = NULL;
> +  FileSize = 0;
> +  FullCapsuleBuffer = NULL;
> +
> +  CapsuleName = Argv[2];
> +  Status = ReadFileToBuffer(CapsuleName, &FileSize, &CapsuleBuffer);
> +  if (EFI_ERROR(Status)) {
> +    Print(L"CapsuleApp: Capsule image (%s) is not found.\n", CapsuleName);
> +    goto Done;
> +  }
> +
> +  ImageTypeId = GetCapsuleImageTypeId(CapsuleBuffer);
> +  if (ImageTypeId == NULL) {
> +    Print(L"CapsuleApp: Capsule ImageTypeId is not found.\n");
> +    goto Done;
> +  }
> +  FwType = GetEsrtFwType(ImageTypeId);
> +  if ((FwType != ESRT_FW_TYPE_SYSTEMFIRMWARE) && (FwType !=
> ESRT_FW_TYPE_DEVICEFIRMWARE)) {
> +    Print(L"CapsuleApp: Capsule FwType is invalid.\n");
> +    goto Done;
> +  }
> +
> +  FullCapsuleBufferSize = NESTED_CAPSULE_HEADER_SIZE + FileSize;
> +  FullCapsuleBuffer = AllocatePool(FullCapsuleBufferSize);
> +  if (FullCapsuleBuffer == NULL) {
> +    Print(L"CapsuleApp: Capsule Buffer size (0x%x) too big.\n",
> FullCapsuleBufferSize);
> +    Status = EFI_OUT_OF_RESOURCES;
> +    goto Done;
> +  }
> +
> +  NestedCapsuleHeader = (EFI_CAPSULE_HEADER *)FullCapsuleBuffer;
> +  ZeroMem(NestedCapsuleHeader, NESTED_CAPSULE_HEADER_SIZE);
> +  CopyGuid(&NestedCapsuleHeader->CapsuleGuid, ImageTypeId);
> +  NestedCapsuleHeader->HeaderSize = NESTED_CAPSULE_HEADER_SIZE;
> +  NestedCapsuleHeader->Flags = (FwType == ESRT_FW_TYPE_DEVICEFIRMWARE) ?
> SYSTEM_FIRMWARE_FLAG : DEVICE_FIRMWARE_FLAG;
> +  NestedCapsuleHeader->CapsuleImageSize = (UINT32)FullCapsuleBufferSize;
> +
> +  CopyMem((UINT8 *)NestedCapsuleHeader + NestedCapsuleHeader->HeaderSize,
> CapsuleBuffer, FileSize);
> +
> +  Status = WriteFileFromBuffer(OutputCapsuleName, FullCapsuleBufferSize,
> FullCapsuleBuffer);
> +  Print(L"CapsuleApp: Write %s %r\n", OutputCapsuleName, Status);
> +
> +Done:
> +  if (CapsuleBuffer != NULL) {
> +    FreePool(CapsuleBuffer);
> +  }
> +
> +  if (FullCapsuleBuffer != NULL) {
> +    FreePool(FullCapsuleBuffer);
> +  }
> +
> +  return Status;
> +}
> +
> +
> +/**
> +  Clear capsule status variable.
> +
> +  @retval EFI_SUCCESS            The capsule status variable is cleared.
> +**/
> +EFI_STATUS
> +ClearCapsuleStatusVariable(
> +  VOID
> +  )
> +{
> +  EFI_STATUS                          Status;
> +  UINT32                              Index;
> +  CHAR16                              CapsuleVarName[20];
> +  CHAR16                              *TempVarName;
> +
> +  StrCpyS (CapsuleVarName, sizeof(CapsuleVarName)/sizeof(CapsuleVarName[0]),
> L"Capsule");
> +  TempVarName = CapsuleVarName + StrLen (CapsuleVarName);
> +  Index = 0;
> +
> +  while (TRUE) {
> +    UnicodeSPrint (TempVarName, 5 * sizeof(CHAR16), L"%04x", Index);
> +
> +    Status = gRT->SetVariable (
> +                    CapsuleVarName,
> +                    &gEfiCapsuleReportGuid,
> +                    EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS |
> EFI_VARIABLE_BOOTSERVICE_ACCESS,
> +                    0,
> +                    (VOID *)NULL
> +                    );
> +    if (EFI_ERROR(Status)) {
> +      //
> +      // There is no capsule variables, quit
> +      //
> +      break;
> +    }
> +
> +    Index++;
> +    if (Index > 0xFFFF) {
> +      break;
> +    }
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Get the active UEFI system partition from bootoption list.
> +
> +  @param[out] Fs    Simple File System protocol on the active UEFI system partition
> +
> +  @retval EFI_SUCCESS   active UEFI system partition found
> +**/
> +EFI_STATUS
> +GetEfiSysPartition(
> +  OUT EFI_SIMPLE_FILE_SYSTEM_PROTOCOL **Fs
> +  )
> +{
> +  EFI_STATUS                       Status;
> +  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL  *FsTemp;
> +  UINTN                            NoHandles;
> +  EFI_HANDLE                       *Handles;
> +  UINTN                            Index;
> +
> +  Handles = NULL;
> +
> +  //
> +  // search for EFI system partition protocol on Boot option device path
> +  //
> +  Status = gBS->LocateHandleBuffer(ByProtocol, &gEfiPartTypeSystemPartGuid, NULL,
> &NoHandles, &Handles);
> +  if (EFI_ERROR(Status)) {
> +    return Status;
> +  }
> +
> +  //
> +  // Skip BootOptions within FV
> +  //
> +  for (Index = 0; Index < NoHandles; Index++) {
> +    Status = gBS->HandleProtocol (Handles[Index], &gEfiSimpleFileSystemProtocolGuid,
> (VOID **)&FsTemp);
> +    if (!EFI_ERROR (Status)){
> +      *Fs = FsTemp;
> +      break;
> +    }
> +  }
> +  return Status;
> +}
> +
> +/**
> +  Copy a list of capsule images to the active UEFI system partition from bootoption
> list.
> +
> +  @param[in] CapsuleBuffer    An array of pointer to capsule images
> +  @param[in] FileSize         An array of UINTN to capsule images size
> +  @param[in] CapsuleNum       The count of capsule images
> +
> +  @retval EFI_SUCCESS   Capsule images are copied to the active UEFI system partition
> +**/
> +EFI_STATUS
> +CopyCapsuleToActiveEfiPartition(
> +  IN VOID                          **CapsuleBuffer,
> +  IN UINTN                         *FileSize,
> +  IN UINTN                         CapsuleNum
> +  )
> +{
> +  EFI_STATUS                       Status;
> +  CHAR16                           *CapsuleName;
> +  UINTN                            Index;
> +  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL  *Fs;
> +  EFI_FILE_HANDLE                  RootDir;
> +  EFI_FILE_HANDLE                  CapsuleDir;
> +  EFI_FILE_HANDLE                  DestHandle;
> +  UINTN                            DataSize;
> +  UINT64                           OsIndication;
> +
> +  RootDir      = NULL;
> +  CapsuleDir   = NULL;
> +
> +  Status = GetEfiSysPartition(&Fs);
> +  if (EFI_ERROR(Status)) {
> +    Print (L"Can not find active UEFI System Partition\n");
> +    return Status;
> +  }
> +
> +  Status = Fs->OpenVolume(Fs, &RootDir);
> +  if (EFI_ERROR(Status)) {
> +    goto EXIT;
> +  }
> +
> +  Status = RootDir->Open(
> +                      RootDir,
> +                      &CapsuleDir,
> +                      EFI_CAPSULE_FROM_FILE_DIR,
> +                      EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE,
> +                      EFI_FILE_DIRECTORY
> +                      );
> +  if (EFI_ERROR(Status)) {
> +    goto EXIT;
> +  }
> +
> +  //
> +  // Read the input files.
> +  //
> +  for (Index = 0; Index < CapsuleNum; Index++) {
> +    CapsuleName = Argv[CapsuleFirstIndex + Index];
> +    Status = CapsuleDir->Open(
> +                           CapsuleDir,
> +                           &DestHandle,
> +                           CapsuleName,
> +                           EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE |
> EFI_FILE_MODE_CREATE,
> +                           EFI_FILE_ARCHIVE
> +                           );
> +    if (EFI_ERROR(Status)) {
> +      Print(L"CapsuleApp: %s open error - %r\n", CapsuleName, Status);
> +      continue;
> +    }
> +
> +    DataSize = FileSize[Index];
> +    Status = DestHandle->Write(
> +                           DestHandle,
> +                           &DataSize,
> +                           CapsuleBuffer[Index]
> +                           );
> +    DestHandle->Close(DestHandle);
> +    if (EFI_ERROR(Status)) {
> +      Print(L"CapsuleApp: %s write error - %r, FileSize - 0x%x\n", CapsuleName,
> Status, FileSize[Index]);
> +    }
> +  }
> +
> +  Status = gRT->GetVariable (
> +                  L"OsIndications",
> +                  &gEfiGlobalVariableGuid,
> +                  NULL,
> +                  &DataSize,
> +                  (VOID *) &OsIndication
> +                  );
> +
> +  if (EFI_ERROR(Status) || DataSize != sizeof(OsIndication)) {
> +    OsIndication = 0;
> +  }
> +
> +  //
> +  // Set OsIndications Variable EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED bit
> +  //
> +  OsIndication |= EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED;
> +  Status = gRT->SetVariable (
> +                  L"OsIndications",
> +                  &gEfiGlobalVariableGuid,
> +                  EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS |
> +                  EFI_VARIABLE_BOOTSERVICE_ACCESS,
> +                  sizeof(OsIndication),
> +                  (VOID *)&OsIndication
> +                  );
> +
> +
> +EXIT:
> +  if (RootDir != NULL) {
> +    RootDir->Close(RootDir);
> +  }
> +
> +  if (CapsuleDir != NULL) {
> +    CapsuleDir->Close(CapsuleDir);
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  Build Gather list for a list of capsule images.
> +
> +  @param[in]  CapsuleBuffer    An array of pointer to capsule images
> +  @param[in]  FileSize         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                         *FileSize,
> +  IN UINTN                         CapsuleNum,
> +  OUT EFI_CAPSULE_BLOCK_DESCRIPTOR **BlockDescriptors
> +  )
> +{
> +  EFI_STATUS                    Status;
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR  *BlockDescriptors1;
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR  *BlockDescriptors2;
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR  *BlockDescriptorPre;
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR  *BlockDescriptorsHeader;
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR  *TempBlockPtr;
> +  UINT8                         *TempDataPtr;
> +  UINTN                         SizeLeft;
> +  UINTN                         Size;
> +  INT32                         Count;
> +  INT32                         Number;
> +  UINTN                         Index;
> +
> +  TempBlockPtr           = NULL;
> +  BlockDescriptors1      = NULL;
> +  BlockDescriptors2      = NULL;
> +  BlockDescriptorPre     = NULL;
> +  BlockDescriptorsHeader = NULL;
> +
> +  for (Index = 0; Index < CapsuleNum; Index++) {
> +    //
> +    // Allocate memory for the descriptors.
> +    //
> +    if (NumberOfDescriptors == 1) {
> +      Count = 2;
> +    } else {
> +      Count = (INT32)(NumberOfDescriptors + 2) / 2;
> +    }
> +
> +    Size               = Count * sizeof (EFI_CAPSULE_BLOCK_DESCRIPTOR);
> +    BlockDescriptors1  = AllocateRuntimeZeroPool (Size);
> +    if (BlockDescriptors1 == NULL) {
> +      Print (L"CapsuleApp: failed to allocate memory for descriptors\n");
> +      Status = EFI_OUT_OF_RESOURCES;
> +      goto ERREXIT;
> +    } else {
> +      Print (L"CapsuleApp: creating capsule descriptors at 0x%X\n", (UINTN)
> BlockDescriptors1);
> +      Print (L"CapsuleApp: capsule data starts          at 0x%X with size 0x%X\n",
> (UINTN) CapsuleBuffer, FileSize);
> +    }
> +
> +    //
> +    // Record descirptor header
> +    //
> +    if (Index == 0) {
> +      BlockDescriptorsHeader = BlockDescriptors1;
> +    }
> +
> +    if (BlockDescriptorPre != NULL) {
> +      BlockDescriptorPre->Union.ContinuationPointer = (UINTN) BlockDescriptors1;
> +      BlockDescriptorPre->Length = 0;
> +    }
> +
> +    //
> +    // Fill them in
> +    //
> +    TempBlockPtr  = BlockDescriptors1;
> +    TempDataPtr   = CapsuleBuffer[Index];
> +    SizeLeft      = FileSize[Index];
> +    for (Number = 0; (Number < Count - 1) && (SizeLeft != 0); Number++) {
> +      //
> +      // Divide remaining data in half
> +      //
> +      if (NumberOfDescriptors != 1) {
> +        if (SizeLeft == 1) {
> +          Size = 1;
> +        } else {
> +          Size = SizeLeft / 2;
> +        }
> +      } else {
> +        Size = SizeLeft;
> +      }
> +      TempBlockPtr->Union.DataBlock    = (UINTN)TempDataPtr;
> +      TempBlockPtr->Length  = Size;
> +      Print (L"CapsuleApp: capsule block/size              0x%X/0x%X\n", (UINTN)
> TempDataPtr, Size);
> +      SizeLeft -= Size;
> +      TempDataPtr += Size;
> +      TempBlockPtr++;
> +    }
> +
> +    //
> +    // Allocate the second list, point the first block's last entry to point
> +    // to this one, and fill this one in. Worst case is that the previous
> +    // list only had one element that pointed here, so we need at least two
> +    // elements -- one to point to all the data, another to terminate the list.
> +    //
> +    if ((NumberOfDescriptors != 1) && (SizeLeft != 0)) {
> +      Count = (INT32)(NumberOfDescriptors + 2) - Count;
> +      if (Count == 1) {
> +        Count++;
> +      }
> +
> +      Size              = Count * sizeof (EFI_CAPSULE_BLOCK_DESCRIPTOR);
> +      BlockDescriptors2 = AllocateRuntimeZeroPool (Size);
> +      if (BlockDescriptors2 == NULL) {
> +        Print (L"CapsuleApp: failed to allocate memory for descriptors\n");
> +        Status = EFI_OUT_OF_RESOURCES;
> +        goto ERREXIT;
> +      }
> +
> +      //
> +      // Point the first list's last element to point to this second list.
> +      //
> +      TempBlockPtr->Union.ContinuationPointer   = (UINTN) BlockDescriptors2;
> +
> +      TempBlockPtr->Length  = 0;
> +      TempBlockPtr = BlockDescriptors2;
> +      for (Number = 0; Number < Count - 1; Number++) {
> +        //
> +        // If second-to-last one, then dump rest to this element
> +        //
> +        if (Number == (Count - 2)) {
> +          Size = SizeLeft;
> +        } else {
> +          //
> +          // Divide remaining data in half
> +          //
> +          if (SizeLeft == 1) {
> +            Size = 1;
> +          } else {
> +            Size = SizeLeft / 2;
> +          }
> +        }
> +
> +        TempBlockPtr->Union.DataBlock    = (UINTN)TempDataPtr;
> +        TempBlockPtr->Length  = Size;
> +        Print (L"CapsuleApp: capsule block/size              0x%X/0x%X\n", (UINTN)
> TempDataPtr, Size);
> +        SizeLeft -= Size;
> +        TempDataPtr += Size;
> +        TempBlockPtr++;
> +        if (SizeLeft == 0) {
> +          break;
> +        }
> +      }
> +    }
> +
> +    BlockDescriptorPre = TempBlockPtr;
> +    BlockDescriptors1  = NULL;
> +  }
> +
> +  //
> +  // Null-terminate.
> +  //
> +  if (TempBlockPtr != NULL) {
> +    TempBlockPtr->Union.ContinuationPointer    = (UINTN)NULL;
> +    TempBlockPtr->Length  = 0;
> +    *BlockDescriptors = BlockDescriptorsHeader;
> +  }
> +
> +  return EFI_SUCCESS;
> +
> +ERREXIT:
> +  if (BlockDescriptors1 != NULL) {
> +    FreePool(BlockDescriptors1);
> +  }
> +
> +  if (BlockDescriptors2 != NULL) {
> +    FreePool(BlockDescriptors2);
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  Clear the Gather list for a list of capsule images.
> +
> +  @param[in]  BlockDescriptors The block descriptors for the capsule images
> +  @param[in]  CapsuleNum       The count of capsule images
> +**/
> +VOID
> +CleanGatherList(
> +  IN EFI_CAPSULE_BLOCK_DESCRIPTOR   *BlockDescriptors,
> +  IN UINTN                          CapsuleNum
> +  )
> +{
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR   *TempBlockPtr;
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR   *TempBlockPtr1;
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR   *TempBlockPtr2;
> +  UINTN                          Index;
> +
> +  if (BlockDescriptors != NULL) {
> +    TempBlockPtr1 = BlockDescriptors;
> +    while (1){
> +      TempBlockPtr = TempBlockPtr1;
> +      for (Index = 0; Index < CapsuleNum; Index++) {
> +        if (TempBlockPtr[Index].Length == 0) {
> +          break;
> +        }
> +      }
> +
> +      if (TempBlockPtr[Index].Union.ContinuationPointer == (UINTN)NULL) {
> +        break;
> +      }
> +
> +      TempBlockPtr2 = (VOID *) ((UINTN) TempBlockPtr->Union.ContinuationPointer);
> +      FreePool(TempBlockPtr1);
> +      TempBlockPtr1 = TempBlockPtr2;
> +    }
> +  }
> +}
> +
> +/**
> +  Print APP usage.
> +**/
> +VOID
> +PrintUsage (
> +  VOID
> +  )
> +{
> +  Print(L"CapsuleApp:  usage\n");
> +  Print(L"  CapsuleApp [-F] <Capsule...> [-NR]\n");
> +  Print(L"  CapsuleApp -S\n");
> +  Print(L"  CapsuleApp -C\n");
> +  Print(L"  CapsuleApp -P\n");
> +  Print(L"  CapsuleApp -E\n");
> +  Print(L"  CapsuleApp -G <BMP> -O <Capsule>\n");
> +  Print(L"  CapsuleApp -N <Capsule> -O <NestedCapsule>\n");
> +  Print(L"  CapsuleApp -D|-DS <Capsule>\n");
> +  Print(L"Parameter:\n");
> +  Print(L"  -F:  Put capsule file to disk.\n");
> +  Print(L"       No -F means to put capsule file in memory.\n");
> +  Print(L"  -NR: No Reset.\n");
> +  Print(L"  -S:  Dump capsule status.\n");
> +  Print(L"  -C:  Clear capsule status.\n");
> +  Print(L"  -P:  Dump FMP protocol info.\n");
> +  Print(L"  -E:  Dump ESRT table info.\n");
> +  Print(L"  -G:  Input BMP file name\n");
> +  Print(L"  -N:  Append Capsule Header accroding to Windows Firmware Update\n");
> +  Print(L"  -O:  Output Capsule file name\n");
> +  Print(L"  -D:  Dump Capsule\n");
> +  Print(L"  -DS: Dump Capsule with System FMP format\n");
> +}
> +
> +/**
> +  Update Capsule image.
> +
> +  @param[in]  ImageHandle     The image handle.
> +  @param[in]  SystemTable     The system table.
> +
> +  @retval EFI_SUCCESS            Command completed successfully.
> +  @retval EFI_INVALID_PARAMETER  Command usage error.
> +  @retval EFI_NOT_FOUND          The input file can't be found.
> +**/
> +EFI_STATUS
> +EFIAPI
> +UefiMain (
> +  IN EFI_HANDLE        ImageHandle,
> +  IN EFI_SYSTEM_TABLE  *SystemTable
> +  )
> +{
> +  EFI_STATUS                    Status;
> +  UINTN                         FileSize[MAX_CAPSULE_NUM];
> +  VOID                          *CapsuleBuffer[MAX_CAPSULE_NUM];
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR  *BlockDescriptors;
> +  EFI_CAPSULE_HEADER             *CapsuleHeaderArray[MAX_CAPSULE_NUM + 1];
> +  UINT64                         MaxCapsuleSize;
> +  EFI_RESET_TYPE                 ResetType;
> +  BOOLEAN                        NeedReset;
> +  BOOLEAN                        NoReset;
> +  BOOLEAN                        NeedCopyOnDisk;
> +  CHAR16                         *CapsuleName;
> +  UINTN                          CapsuleNum;
> +  UINTN                          Index;
> +
> +  Status = GetArg();
> +  if (EFI_ERROR(Status)) {
> +    PrintUsage();
> +    return Status;
> +  }
> +  if (Argc < 2) {
> +    PrintUsage();
> +    CleanArg();
> +    return EFI_INVALID_PARAMETER;
> +  }
> +  if ((StrCmp(Argv[1], L"-D") == 0) ||
> +      (StrCmp(Argv[1], L"-DS") == 0)) {
> +    Status = DumpCapsule();
> +    CleanArg();
> +    return Status;
> +  }
> +  if (StrCmp(Argv[1], L"-G") == 0) {
> +    Status = CreateBmpFmp();
> +    CleanArg();
> +    return Status;
> +  }
> +  if (StrCmp(Argv[1], L"-N") == 0) {
> +    Status = CreateNestedFmp();
> +    CleanArg();
> +    return Status;
> +  }
> +  if (StrCmp(Argv[1], L"-S") == 0) {
> +    Status = DmpCapsuleStatusVariable();
> +    CleanArg();
> +    return EFI_SUCCESS;
> +  }
> +  if (StrCmp(Argv[1], L"-C") == 0) {
> +    Status = ClearCapsuleStatusVariable();
> +    CleanArg();
> +    return Status;
> +  }
> +  if (StrCmp(Argv[1], L"-P") == 0) {
> +    DumpFmpData();
> +    CleanArg();
> +    return EFI_SUCCESS;
> +  }
> +  if (StrCmp(Argv[1], L"-E") == 0) {
> +    DumpEsrtData();
> +    CleanArg();
> +    return EFI_SUCCESS;
> +  }
> +  if (StrCmp(Argv[1], L"-F") == 0) {
> +    NeedCopyOnDisk = TRUE;
> +    CapsuleFirstIndex = 2;
> +  } else {
> +    NeedCopyOnDisk = FALSE;
> +    CapsuleFirstIndex = 1;
> +  }
> +  if (StrCmp(Argv[Argc - 1], L"-NR") == 0) {
> +    NoReset = TRUE;
> +    CapsuleLastIndex = Argc - 2;
> +  } else {
> +    NoReset = FALSE;
> +    CapsuleLastIndex = Argc - 1;
> +  }
> +  CapsuleNum = CapsuleLastIndex - CapsuleFirstIndex + 1;
> +
> +  if (CapsuleFirstIndex > CapsuleLastIndex) {
> +    Print(L"CapsuleApp: NO capsule image.\n");
> +    CleanArg();
> +    return EFI_UNSUPPORTED;
> +  }
> +  if (CapsuleNum > MAX_CAPSULE_NUM) {
> +    Print(L"CapsuleApp: Too many capsule images.\n");
> +    CleanArg();
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  ZeroMem(&CapsuleBuffer, sizeof(CapsuleBuffer));
> +  ZeroMem(&FileSize, sizeof(FileSize));
> +  BlockDescriptors = NULL;
> +
> +  for (Index = 0; Index < CapsuleNum; Index++) {
> +    CapsuleName = Argv[CapsuleFirstIndex + Index];
> +    Status = ReadFileToBuffer(CapsuleName, &FileSize[Index], &CapsuleBuffer[Index]);
> +    if (EFI_ERROR(Status)) {
> +      Print(L"CapsuleApp: capsule image (%s) is not found.\n", CapsuleName);
> +      goto Done;
> +    }
> +  }
> +
> +  if (NeedCopyOnDisk) {
> +    Status = CopyCapsuleToActiveEfiPartition(CapsuleBuffer, FileSize, CapsuleNum);
> +  } else {
> +    //
> +    // Every capsule use 2 descriptor 1 for data 1 for end
> +    //
> +    Status = BuildGatherList(CapsuleBuffer, FileSize, CapsuleNum, &BlockDescriptors);
> +  }
> +  if (EFI_ERROR(Status)) {
> +    goto Done;
> +  }
> +
> +  //
> +  // Call the runtime service capsule.
> +  //
> +  NeedReset = FALSE;
> +  for (Index = 0; Index < CapsuleNum; Index++) {
> +    CapsuleHeaderArray[Index] = (EFI_CAPSULE_HEADER *) CapsuleBuffer[Index];
> +    if ((CapsuleHeaderArray[Index]->Flags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET) != 0)
> {
> +      NeedReset = TRUE;
> +    }
> +  }
> +  CapsuleHeaderArray[CapsuleNum] = NULL;
> +  if (NoReset) {
> +    NeedReset = FALSE;
> +  }
> +
> +  //
> +  // Inquire platform capability of UpdateCapsule.
> +  //
> +  Status = gRT->QueryCapsuleCapabilities (CapsuleHeaderArray, CapsuleNum,
> &MaxCapsuleSize, &ResetType);
> +  if (EFI_ERROR(Status)) {
> +    Print (L"CapsuleApp: failed to query capsule capability - %r\n", Status);
> +    goto Done;
> +  }
> +
> +  for (Index = 0; Index < CapsuleNum; Index++) {
> +    if (FileSize[Index] > MaxCapsuleSize) {
> +      Print (L"CapsuleApp: capsule is too large to update, %ld is allowed\n",
> MaxCapsuleSize);
> +      Status = EFI_UNSUPPORTED;
> +      goto Done;
> +    }
> +  }
> +
> +  //
> +  // Check whether the input capsule image has the flag of persist across system
> reset.
> +  //
> +  if (NeedReset) {
> +    Status = gRT->UpdateCapsule(CapsuleHeaderArray,CapsuleNum,(UINTN)
> BlockDescriptors);
> +    if (Status != EFI_SUCCESS) {
> +      Print (L"CapsuleApp: failed to update capsule - %r\n", Status);
> +      goto Done;
> +    }
> +    //
> +    // For capsule who has reset flag, after calling UpdateCapsule service,triger a
> +    // system reset to process capsule persist across a system reset.
> +    //
> +    gRT->ResetSystem (ResetType, EFI_SUCCESS, 0, NULL);
> +  } else {
> +    //
> +    // For capsule who has no reset flag, only call UpdateCapsule Service without a
> +    // system reset. The service will process the capsule immediately.
> +    //
> +    Status = gRT->UpdateCapsule (CapsuleHeaderArray,CapsuleNum,(UINTN)
> BlockDescriptors);
> +    if (Status != EFI_SUCCESS) {
> +      Print (L"CapsuleApp: failed to update capsule - %r\n", Status);
> +    }
> +  }
> +
> +  Status = EFI_SUCCESS;
> +
> +Done:
> +  for (Index = 0; Index < CapsuleNum; Index++) {
> +    if (CapsuleBuffer[Index] != NULL) {
> +      FreePool (CapsuleBuffer[Index]);
> +    }
> +  }
> +
> +  CleanGatherList(BlockDescriptors, CapsuleNum);
> +  CleanArg();
> +
> +  return Status;
> +}
> diff --git a/MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf
> b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf
> new file mode 100644
> index 0000000..7ee44fc
> --- /dev/null
> +++ b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf
> @@ -0,0 +1,71 @@
> +##  @file
> +#  A shell application that triggers capsule update process.
> +#
> +# This application can trigger capsule update process. It can also
> +# generate capsule image, or dump capsule variable information.
> +#
> +#  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
> +#  This program and the accompanying materials
> +#  are licensed and made available under the terms and conditions of the BSD License
> +#  which accompanies this distribution.  The full text of the license may be found at
> +#  http://opensource.org/licenses/bsd-license.php
> +#
> +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +#
> +##
> +
> +[Defines]
> +  INF_VERSION                    = 0x00010006
> +  BASE_NAME                      = CapsuleApp
> +  MODULE_UNI_FILE                = CapsuleApp.uni
> +  FILE_GUID                      = 4CEF31DA-8682-4274-9CC4-AEE7516A5E7B
> +  MODULE_TYPE                    = UEFI_APPLICATION
> +  VERSION_STRING                 = 1.0
> +  ENTRY_POINT                    = UefiMain
> +
> +#
> +# The following information is for reference only and not required by the build tools.
> +#
> +#  VALID_ARCHITECTURES           = IA32 X64
> +#
> +
> +[Sources]
> +  CapsuleApp.c
> +  CapsuleDump.c
> +  AppSupport.c
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +
> +[Guids]
> +  gEfiFileInfoGuid
> +  gEfiPartTypeSystemPartGuid
> +  gEfiGlobalVariableGuid
> +  gEfiCapsuleReportGuid
> +  gEfiFmpCapsuleGuid
> +  gWindowsUxCapsuleGuid
> +  gEfiCertTypeRsa2048Sha256Guid
> +  gEfiCertPkcs7Guid
> +  gEfiSystemResourceTableGuid
> +
> +[Protocols]
> +  gEfiLoadedImageProtocolGuid
> +  gEfiSimpleFileSystemProtocolGuid
> +  gEfiGraphicsOutputProtocolGuid
> +  gEfiFirmwareManagementProtocolGuid
> +
> +[LibraryClasses]
> +  BaseLib
> +  UefiApplicationEntryPoint
> +  DebugLib
> +  MemoryAllocationLib
> +  UefiBootServicesTableLib
> +  UefiRuntimeServicesTableLib
> +  UefiLib
> +  PrintLib
> +  EdkiiSystemCapsuleLib
> +
> +[UserExtensions.TianoCore."ExtraFiles"]
> +  CapsuleAppExtra.uni
> diff --git a/MdeModulePkg/Application/CapsuleApp/CapsuleApp.uni
> b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.uni
> new file mode 100644
> index 0000000..54d6e12
> --- /dev/null
> +++ b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.uni
> @@ -0,0 +1,22 @@
> +// /** @file
> +// A shell application that triggers capsule update process.
> +//
> +// This application can trigger capsule update process. It can also
> +// generate capsule image, or dump capsule variable information.
> +//
> +// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
> +//
> +// This program and the accompanying materials
> +// are licensed and made available under the terms and conditions of the BSD License
> +// which accompanies this distribution. The full text of the license may be found at
> +// http://opensource.org/licenses/bsd-license.php
> +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +//
> +// **/
> +
> +
> +#string STR_MODULE_ABSTRACT             #language en-US "A shell application that
> triggers capsule update process."
> +
> +#string STR_MODULE_DESCRIPTION          #language en-US "This application can trigger
> capsule update process. It can also generate capsule image, or dump capsule variable
> information."
> +
> diff --git a/MdeModulePkg/Application/CapsuleApp/CapsuleAppExtra.uni
> b/MdeModulePkg/Application/CapsuleApp/CapsuleAppExtra.uni
> new file mode 100644
> index 0000000..b5a8840
> --- /dev/null
> +++ b/MdeModulePkg/Application/CapsuleApp/CapsuleAppExtra.uni
> @@ -0,0 +1,19 @@
> +// /** @file
> +// CapsuleApp Localized Strings and Content
> +//
> +// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
> +//
> +// This program and the accompanying materials
> +// are licensed and made available under the terms and conditions of the BSD License
> +// which accompanies this distribution. The full text of the license may be found at
> +// http://opensource.org/licenses/bsd-license.php
> +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +//
> +// **/
> +
> +#string STR_PROPERTIES_MODULE_NAME
> +#language en-US
> +"Capsule Application"
> +
> +
> diff --git a/MdeModulePkg/Application/CapsuleApp/CapsuleDump.c
> b/MdeModulePkg/Application/CapsuleApp/CapsuleDump.c
> new file mode 100644
> index 0000000..c56f41f
> --- /dev/null
> +++ b/MdeModulePkg/Application/CapsuleApp/CapsuleDump.c
> @@ -0,0 +1,840 @@
> +/** @file
> +  Dump Capsule image information.
> +
> +  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the BSD License
> +  which accompanies this distribution.  The full text of the license may be found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +
> +**/
> +
> +#include <PiDxe.h>
> +#include <Library/BaseLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/UefiRuntimeServicesTableLib.h>
> +#include <Library/UefiLib.h>
> +#include <Library/PrintLib.h>
> +#include <Library/EdkiiSystemCapsuleLib.h>
> +#include <Protocol/FirmwareManagement.h>
> +#include <Guid/ImageAuthentication.h>
> +#include <Guid/EdkiiSystemFmpCapsule.h>
> +#include <Guid/CapsuleReport.h>
> +#include <Guid/SystemResourceTable.h>
> +#include <Guid/FmpCapsule.h>
> +#include <IndustryStandard/WindowsUxCapsule.h>
> +
> +/**
> +  Read a file.
> +
> +  @param FileName        The file to be read.
> +  @param BufferSize      The file buffer size
> +  @param Buffer          The file buffer
> +
> +  @retval EFI_SUCCESS    Read file successfully
> +  @retval EFI_NOT_FOUND  File not found
> +**/
> +EFI_STATUS
> +ReadFileToBuffer(
> +  IN  CHAR16                               *FileName,
> +  OUT UINTN                                *BufferSize,
> +  OUT VOID                                 **Buffer
> +  );
> +
> +extern UINTN  Argc;
> +extern CHAR16 *Argv[];
> +
> +/**
> +  Dump UX capsule information.
> +
> +  @param CapsuleHeader      The UX capsule header
> +**/
> +VOID
> +DumpUxCapsule(
> +  IN EFI_CAPSULE_HEADER  *CapsuleHeader
> +  )
> +{
> +  EFI_DISPLAY_CAPSULE                           *DisplayCapsule;
> +  DisplayCapsule = (EFI_DISPLAY_CAPSULE *)CapsuleHeader;
> +  Print(L"[UxCapusule]\n");
> +  Print(L"CapsuleHeader:\n");
> +  Print(L"  CapsuleGuid      - %g\n", &DisplayCapsule->CapsuleHeader.CapsuleGuid);
> +  Print(L"  HeaderSize       - 0x%x\n", DisplayCapsule->CapsuleHeader.HeaderSize);
> +  Print(L"  Flags            - 0x%x\n", DisplayCapsule->CapsuleHeader.Flags);
> +  Print(L"  CapsuleImageSize - 0x%x\n", DisplayCapsule-
> >CapsuleHeader.CapsuleImageSize);
> +  Print(L"ImagePayload:\n");
> +  Print(L"  Version          - 0x%x\n", DisplayCapsule->ImagePayload.Version);
> +  Print(L"  Checksum         - 0x%x\n", DisplayCapsule->ImagePayload.Checksum);
> +  Print(L"  ImageType        - 0x%x\n", DisplayCapsule->ImagePayload.ImageType);
> +  Print(L"  Mode             - 0x%x\n", DisplayCapsule->ImagePayload.Mode);
> +  Print(L"  OffsetX          - 0x%x\n", DisplayCapsule->ImagePayload.OffsetX);
> +  Print(L"  OffsetY          - 0x%x\n", DisplayCapsule->ImagePayload.OffsetY);
> +}
> +
> +/**
> +  Dump FMP image authentication information.
> +
> +  @param Image      The FMP capsule image
> +  @param ImageSize  The size of the FMP capsule image in bytes.
> +
> +  @return the size of FMP authentication.
> +**/
> +UINTN
> +DumpImageAuthentication(
> +  IN VOID   *Image,
> +  IN UINTN  ImageSize
> +  )
> +{
> +  EFI_FIRMWARE_IMAGE_AUTHENTICATION             *ImageAuthentication;
> +
> +  ImageAuthentication = Image;
> +  if (CompareGuid(&ImageAuthentication->AuthInfo.CertType, &gEfiCertPkcs7Guid) ||
> +      CompareGuid(&ImageAuthentication->AuthInfo.CertType,
> &gEfiCertTypeRsa2048Sha256Guid)) {
> +    Print(L"[ImageAuthentication]\n");
> +    Print(L"  MonotonicCount   - 0x%lx\n", ImageAuthentication->MonotonicCount);
> +    Print(L"WIN_CERTIFICATE:\n");
> +    Print(L"  dwLength         - 0x%x\n", ImageAuthentication->AuthInfo.Hdr.dwLength);
> +    Print(L"  wRevision        - 0x%x\n", ImageAuthentication-
> >AuthInfo.Hdr.wRevision);
> +    Print(L"  wCertificateType - 0x%x\n", ImageAuthentication-
> >AuthInfo.Hdr.wCertificateType);
> +    Print(L"  CertType         - %g\n", &ImageAuthentication->AuthInfo.CertType);
> +    return sizeof(ImageAuthentication->MonotonicCount) + ImageAuthentication-
> >AuthInfo.Hdr.dwLength;
> +  } else {
> +    return 0;
> +  }
> +}
> +
> +/**
> +  Dump EDKII system FMP capsule.
> +
> +  @param Image      The EDKII system FMP capsule.
> +  @param ImageSize  The size of the EDKII system FMP capsule in bytes.
> +**/
> +VOID
> +DumpEdkiiSystemFmpCapsule(
> +  IN VOID   *Image,
> +  IN UINTN  ImageSize
> +  )
> +{
> +  UINTN                                         ImageOffset;
> +  VOID                                          *BiosImage;
> +  UINTN                                         BiosImageSize;
> +  BOOLEAN                                       Result;
> +  EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR        *TempImageFmpInfo;
> +  EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR        *ImageFmpInfo;
> +  UINTN                                         ImageFmpInfoSize;
> +
> +  //
> +  // We do not know if there is EFI_FIRMWARE_IMAGE_AUTHENTICATION.
> +  // so just *try* to parse it
> +  //
> +  ImageOffset = DumpImageAuthentication(Image, ImageSize);
> +  Image = (UINT8 *)Image + ImageOffset;
> +  ImageSize -= ImageOffset;
> +  Print(L"[Image]\n");
> +  Print(L"  ImageSize   - 0x%x\n", ImageSize);
> +
> +  Result = ExtractConfigImage(Image, ImageSize, &BiosImage, &BiosImageSize);
> +  if (Result) {
> +    Print(L"  ConfigFileSize  - 0x%x\n", BiosImageSize);
> +  }
> +  Result = ExtractDriverFvImage(Image, ImageSize, &BiosImage, &BiosImageSize);
> +  if (Result) {
> +    Print(L"  DriverFvSize    - 0x%x\n", BiosImageSize);
> +  }
> +  Result = ExtractSystemFirmwareImage(Image, ImageSize, &BiosImage, &BiosImageSize);
> +  if (Result) {
> +    Print(L"  BiosImageSize   - 0x%x\n", BiosImageSize);
> +  }
> +  Result = ExtractSystemFirmwareImageFmpInfo(BiosImage, BiosImageSize,
> &TempImageFmpInfo, &ImageFmpInfoSize);
> +  if (Result) {
> +    ImageFmpInfo = AllocateCopyPool(ImageFmpInfoSize, TempImageFmpInfo);
> +    if (ImageFmpInfo != NULL) {
> +      Print(L"[ImageFmpInfo]\n");
> +      Print(L"  Signature                      - 0x%x\n", ImageFmpInfo->Signature);
> +      Print(L"  HeaderLength                   - 0x%x\n", ImageFmpInfo->HeaderLength);
> +      Print(L"  Length                         - 0x%x\n", ImageFmpInfo->Length);
> +      Print(L"  PackageVersion                 - 0x%x\n", ImageFmpInfo-
> >PackageVersion);
> +      Print(L"  PackageVersionNameStringOffset - 0x%x\n", ImageFmpInfo-
> >PackageVersionNameStringOffset);
> +      if (ImageFmpInfo->PackageVersionNameStringOffset != 0) {
> +        Print(L"                                 - %s\n", (UINT8 *)ImageFmpInfo +
> ImageFmpInfo->PackageVersionNameStringOffset);
> +      }
> +      Print(L"  ImageIndex                     - 0x%x\n", ImageFmpInfo->ImageIndex);
> +      Print(L"  ImageTypeId                    - %g\n", &ImageFmpInfo->ImageTypeId);
> +      Print(L"  ImageId                        - 0x%lx\n", ImageFmpInfo->ImageId);
> +      Print(L"  ImageIdNameStringOffset        - 0x%x\n", ImageFmpInfo-
> >ImageIdNameStringOffset);
> +      if (ImageFmpInfo->ImageIdNameStringOffset != 0) {
> +        Print(L"                                 - %s\n", (UINT8 *)ImageFmpInfo +
> ImageFmpInfo->ImageIdNameStringOffset);
> +      }
> +      Print(L"  Version                        - 0x%x\n", ImageFmpInfo->Version);
> +      Print(L"  VersionNameStringOffset        - 0x%x\n", ImageFmpInfo-
> >VersionNameStringOffset);
> +      if (ImageFmpInfo->VersionNameStringOffset != 0) {
> +        Print(L"                                 - %s\n", (UINT8 *)ImageFmpInfo +
> ImageFmpInfo->VersionNameStringOffset);
> +      }
> +      Print(L"  Size                           - 0x%lx\n", ImageFmpInfo->Size);
> +      Print(L"  AttributesSupported            - 0x%lx\n", ImageFmpInfo-
> >AttributesSupported);
> +      Print(L"  AttributesSetting              - 0x%lx\n", ImageFmpInfo-
> >AttributesSetting);
> +      Print(L"  Compatibilities                - 0x%lx\n", ImageFmpInfo-
> >Compatibilities);
> +      Print(L"  LowestSupportedImageVersion    - 0x%x\n", ImageFmpInfo-
> >LowestSupportedImageVersion);
> +      Print(L"  LastAttemptVersion             - 0x%x\n", ImageFmpInfo-
> >LastAttemptVersion);
> +      Print(L"  LastAttemptStatus              - 0x%x\n", ImageFmpInfo-
> >LastAttemptStatus);
> +      Print(L"  HardwareInstance               - 0x%lx\n", ImageFmpInfo-
> >HardwareInstance);
> +      Print(L"  Version                        - 0x%x\n", ImageFmpInfo->Version);
> +      FreePool(ImageFmpInfo);
> +    }
> +  }
> +}
> +
> +/**
> +  Dump a non-nested FMP capsule.
> +
> +  @param  CapsuleHeader  A pointer to CapsuleHeader
> +  @param  IsSystemFmp    If it is a system FMP
> +**/
> +VOID
> +DumpFmpCapsule(
> +  IN EFI_CAPSULE_HEADER  *CapsuleHeader,
> +  IN BOOLEAN             IsSystemFmp
> +  )
> +{
> +  EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER        *FmpCapsuleHeader;
> +  UINT64                                        *ItemOffsetList;
> +  UINTN                                         Index;
> +  UINTN                                         Count;
> +  EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER  *FmpImageHeader;
> +  VOID                                          *Image;
> +
> +  Print(L"[FmpCapusule]\n");
> +  Print(L"CapsuleHeader:\n");
> +  Print(L"  CapsuleGuid      - %g\n", &CapsuleHeader->CapsuleGuid);
> +  Print(L"  HeaderSize       - 0x%x\n", CapsuleHeader->HeaderSize);
> +  Print(L"  Flags            - 0x%x\n", CapsuleHeader->Flags);
> +  Print(L"  CapsuleImageSize - 0x%x\n", CapsuleHeader->CapsuleImageSize);
> +
> +  FmpCapsuleHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *)((UINT8 *)CapsuleHeader
> + CapsuleHeader->HeaderSize);
> +  ItemOffsetList = (UINT64 *)(FmpCapsuleHeader + 1);
> +  Print(L"FmpHeader:\n");
> +  Print(L"  Version             - 0x%x\n", FmpCapsuleHeader->Version);
> +  Print(L"  EmbeddedDriverCount - 0x%x\n", FmpCapsuleHeader->EmbeddedDriverCount);
> +  Print(L"  PayloadItemCount    - 0x%x\n", FmpCapsuleHeader->PayloadItemCount);
> +  Count = FmpCapsuleHeader->EmbeddedDriverCount + FmpCapsuleHeader->PayloadItemCount;
> +  for (Index = 0; Index < Count; Index++) {
> +    Print(L"  Offset[%d]           - 0x%x\n", Index, ItemOffsetList[Index]);
> +  }
> +
> +  for (Index = FmpCapsuleHeader->EmbeddedDriverCount; Index < Count; Index++) {
> +    Print(L"FmpPayload[%d] ImageHeader:\n", Index);
> +    FmpImageHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *)((UINT8
> *)FmpCapsuleHeader + ItemOffsetList[Index]);
> +    Print(L"  Version                - 0x%x\n", FmpImageHeader->Version);
> +    Print(L"  UpdateImageTypeId      - %g\n", &FmpImageHeader->UpdateImageTypeId);
> +    Print(L"  UpdateImageIndex       - 0x%x\n", FmpImageHeader->UpdateImageIndex);
> +    Print(L"  UpdateImageSize        - 0x%x\n", FmpImageHeader->UpdateImageSize);
> +    Print(L"  UpdateVendorCodeSize   - 0x%x\n", FmpImageHeader->UpdateVendorCodeSize);
> +    if (FmpImageHeader->Version >=
> EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {
> +      Print(L"  UpdateHardwareInstance - 0x%lx\n", FmpImageHeader-
> >UpdateHardwareInstance);
> +    }
> +    if (FmpImageHeader->Version >=
> EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {
> +      Image = (UINT8 *)(FmpImageHeader + 1);
> +    }  else {
> +      Image = (UINT8 *)FmpImageHeader +
> OFFSET_OF(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER, UpdateHardwareInstance);
> +    }
> +    if (IsSystemFmp) {
> +      DumpEdkiiSystemFmpCapsule(Image, FmpImageHeader->UpdateImageSize);
> +    }
> +  }
> +}
> +
> +/**
> +  Return if there is a FMP header below capsule header.
> +
> +  @param[in] CapsuleHeader A pointer to EFI_CAPSULE_HEADER
> +
> +  @retval TRUE  There is a FMP header below capsule header.
> +  @retval FALSE There is not a FMP header below capsule header
> +**/
> +BOOLEAN
> +IsNestedFmpCapsule(
> +  IN EFI_CAPSULE_HEADER         *CapsuleHeader
> +  )
> +{
> +  EFI_STATUS                 Status;
> +  EFI_SYSTEM_RESOURCE_TABLE  *Esrt;
> +  EFI_SYSTEM_RESOURCE_ENTRY  *EsrtEntry;
> +  UINTN                      Index;
> +  BOOLEAN                    EsrtGuidFound;
> +  EFI_CAPSULE_HEADER         *NestedCapsuleHeader;
> +  UINTN                      NestedCapsuleSize;
> +
> +  //
> +  // Check ESRT
> +  //
> +  EsrtGuidFound = FALSE;
> +  Status = EfiGetSystemConfigurationTable(&gEfiSystemResourceTableGuid, (VOID
> **)&Esrt);
> +  if (!EFI_ERROR(Status)) {
> +    EsrtEntry = (VOID *)(Esrt + 1);
> +    for (Index = 0; Index < Esrt->FwResourceCount; Index++, EsrtEntry++) {
> +      if (CompareGuid(&EsrtEntry->FwClass, &CapsuleHeader->CapsuleGuid)) {
> +        EsrtGuidFound = TRUE;
> +        break;
> +      }
> +    }
> +  }
> +
> +  if (!EsrtGuidFound) {
> +    return FALSE;
> +  }
> +
> +  //
> +  // Check nested capsule header
> +  // FMP GUID after ESRT one
> +  //
> +  NestedCapsuleHeader = (EFI_CAPSULE_HEADER *)((UINT8 *)CapsuleHeader + CapsuleHeader-
> >HeaderSize);
> +  NestedCapsuleSize = (UINTN)CapsuleHeader + CapsuleHeader->HeaderSize -
> (UINTN)NestedCapsuleHeader;
> +  if (NestedCapsuleSize < sizeof(EFI_CAPSULE_HEADER)) {
> +    return FALSE;
> +  }
> +  if (!CompareGuid(&NestedCapsuleHeader->CapsuleGuid, &gEfiFmpCapsuleGuid)) {
> +    return FALSE;
> +  }
> +  return TRUE;
> +}
> +
> +/**
> +  Dump capsule information
> +
> +  @retval EFI_SUCCESS            The capsule information is dumped.
> +  @retval EFI_UNSUPPORTED        Input parameter is not valid.
> +**/
> +EFI_STATUS
> +DumpCapsule(
> +  VOID
> +  )
> +{
> +  CHAR16                                        *CapsuleName;
> +  VOID                                          *Buffer;
> +  UINTN                                         FileSize;
> +  BOOLEAN                                       IsSystemFmp;
> +  EFI_CAPSULE_HEADER                            *CapsuleHeader;
> +  EFI_STATUS                                    Status;
> +
> +  if (Argc != 3) {
> +    Print(L"CapsuleApp: Invalid Parameter.\n");
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  IsSystemFmp = FALSE;
> +  if (StrCmp(Argv[1], L"-DS") == 0) {
> +    IsSystemFmp = TRUE;
> +  }
> +
> +  CapsuleName = Argv[2];
> +  Status = ReadFileToBuffer(CapsuleName, &FileSize, &Buffer);
> +  if (EFI_ERROR(Status)) {
> +    Print(L"CapsuleApp: Capsule (%s) is not found.\n", CapsuleName);
> +    goto Done;
> +  }
> +
> +  CapsuleHeader = Buffer;
> +  if (CompareGuid(&CapsuleHeader->CapsuleGuid, &gWindowsUxCapsuleGuid)) {
> +    DumpUxCapsule(CapsuleHeader);
> +    Status = EFI_SUCCESS;
> +    goto Done;
> +  }
> +
> +  if (CompareGuid(&CapsuleHeader->CapsuleGuid, &gEfiFmpCapsuleGuid)) {
> +    DumpFmpCapsule(CapsuleHeader, IsSystemFmp);
> +  }
> +  if (IsNestedFmpCapsule(CapsuleHeader)) {
> +    Print(L"[NestedCapusule]\n");
> +    Print(L"CapsuleHeader:\n");
> +    Print(L"  CapsuleGuid      - %g\n", &CapsuleHeader->CapsuleGuid);
> +    Print(L"  HeaderSize       - 0x%x\n", CapsuleHeader->HeaderSize);
> +    Print(L"  Flags            - 0x%x\n", CapsuleHeader->Flags);
> +    Print(L"  CapsuleImageSize - 0x%x\n", CapsuleHeader->CapsuleImageSize);
> +    DumpFmpCapsule((EFI_CAPSULE_HEADER *)((UINTN)CapsuleHeader + CapsuleHeader-
> >HeaderSize), IsSystemFmp);
> +  }
> +
> +Done:
> +  FreePool(Buffer);
> +  return Status;
> +}
> +
> +/**
> +  Dump capsule status variable.
> +
> +  @retval EFI_SUCCESS            The capsule status variable is dumped.
> +  @retval EFI_UNSUPPORTED        Input parameter is not valid.
> +**/
> +EFI_STATUS
> +DmpCapsuleStatusVariable(
> +  VOID
> +  )
> +{
> +  EFI_STATUS                          Status;
> +  UINT32                              Index;
> +  CHAR16                              CapsuleVarName[20];
> +  CHAR16                              *TempVarName;
> +  EFI_CAPSULE_RESULT_VARIABLE_HEADER  *CapsuleResult;
> +  EFI_CAPSULE_RESULT_VARIABLE_FMP     *CapsuleResultFmp;
> +  UINTN                               CapsuleFileNameSize;
> +  CHAR16                              CapsuleIndexData[12];
> +  CHAR16                              *CapsuleIndex;
> +
> +  Status = GetVariable2(
> +             L"CapsuleMax",
> +             &gEfiCapsuleReportGuid,
> +             (VOID **)&CapsuleIndex,
> +             NULL
> +             );
> +  if (!EFI_ERROR(Status)) {
> +    CopyMem(CapsuleIndexData, CapsuleIndex, 11 * sizeof(CHAR16));
> +    CapsuleIndexData[11] = 0;
> +    Print(L"CapsuleMax - %s\n", CapsuleIndexData);
> +    FreePool(CapsuleIndex);
> +  }
> +  Status = GetVariable2(
> +             L"CapsuleLast",
> +             &gEfiCapsuleReportGuid,
> +             (VOID **)&CapsuleIndex,
> +             NULL
> +             );
> +  if (!EFI_ERROR(Status)) {
> +    CopyMem(CapsuleIndexData, CapsuleIndex, 11 * sizeof(CHAR16));
> +    CapsuleIndexData[11] = 0;
> +    Print(L"CapsuleLast - %s\n", CapsuleIndexData);
> +    FreePool(CapsuleIndex);
> +  }
> +
> +
> +  StrCpyS (CapsuleVarName, sizeof(CapsuleVarName)/sizeof(CapsuleVarName[0]),
> L"Capsule");
> +  TempVarName = CapsuleVarName + StrLen (CapsuleVarName);
> +  Index = 0;
> +
> +  while (TRUE) {
> +    UnicodeSPrint (TempVarName, 5 * sizeof(CHAR16), L"%04x", Index);
> +
> +    Status = GetVariable2 (
> +               CapsuleVarName,
> +               &gEfiCapsuleReportGuid,
> +               (VOID **) &CapsuleResult,
> +               NULL
> +               );
> +    if (Status == EFI_NOT_FOUND) {
> +      break;
> +    } else if (EFI_ERROR(Status)) {
> +      continue;
> +    }
> +
> +    //
> +    // display capsule process status
> +    //
> +    if (CapsuleResult->VariableTotalSize >=
> sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER)) {
> +      Print (L"CapsuleName: %s\n", CapsuleVarName);
> +      Print (L"  Capsule Guid: %g\n", &CapsuleResult->CapsuleGuid);
> +      Print (L"  Capsule ProcessedTime: %t\n", &CapsuleResult->CapsuleProcessed);
> +      Print (L"  Capsule Status: %r\n", CapsuleResult->CapsuleStatus);
> +    }
> +
> +    if (CompareGuid(&CapsuleResult->CapsuleGuid, &gEfiFmpCapsuleGuid)) {
> +      if (CapsuleResult->VariableTotalSize >=
> sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER) + sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP)) {
> +        CapsuleResultFmp = (EFI_CAPSULE_RESULT_VARIABLE_FMP *)(CapsuleResult + 1);
> +        Print(L"  Capsule FMP Version: 0x%x\n", CapsuleResultFmp->Version);
> +        Print(L"  Capsule FMP PayloadIndex: 0x%x\n", CapsuleResultFmp->PayloadIndex);
> +        Print(L"  Capsule FMP UpdateImageIndex: 0x%x\n", CapsuleResultFmp-
> >UpdateImageIndex);
> +        Print(L"  Capsule FMP UpdateImageTypeId: %g\n", &CapsuleResultFmp-
> >UpdateImageTypeId);
> +        if (CapsuleResult->VariableTotalSize >
> sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER) + sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP)) {
> +          Print(L"  Capsule FMP CapsuleFileName: %s\n", (CapsuleResultFmp + 1));
> +          CapsuleFileNameSize = StrSize((CHAR16 *)(CapsuleResultFmp + 1));
> +          if (CapsuleResult->VariableTotalSize >
> sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER) + sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP) +
> CapsuleFileNameSize) {
> +            Print(L"  Capsule FMP CapsuleTarget: %s\n", (UINT8 *)(CapsuleResultFmp +
> 1) + CapsuleFileNameSize);
> +          }
> +        }
> +      }
> +    }
> +
> +    FreePool(CapsuleResult);
> +
> +    Index++;
> +    if (Index > 0xFFFF) {
> +      break;
> +    }
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +CHAR8 *mFwTypeString[] = {
> +  "Unknown",
> +  "SystemFirmware",
> +  "DeviceFirmware",
> +  "UefiDriver",
> +};
> +
> +CHAR8 *mLastAttemptStatusString[] = {
> +  "Success",
> +  "Error: Unsuccessful",
> +  "Error: Insufficient Resources",
> +  "Error: Incorrect Version",
> +  "Error: Invalid Format",
> +  "Error: Auth Error",
> +  "Error: Power Event AC",
> +  "Error: Power Event Battery",
> +};
> +
> +/**
> +  Convert FwType to a string.
> +
> +  @param FwType  FwType in ESRT
> +
> +  @return a string for FwType.
> +**/
> +CHAR8 *
> +FwTypeToString(
> +  IN UINT32 FwType
> +  )
> +{
> +  if (FwType < sizeof(mFwTypeString) / sizeof(mFwTypeString[0])) {
> +    return mFwTypeString[FwType];
> +  } else {
> +    return "Invalid";
> +  }
> +}
> +
> +/**
> +  Convert LastAttemptStatus to a string.
> +
> +  @param LastAttemptStatus  LastAttemptStatus in FMP or ESRT
> +
> +  @return a string for LastAttemptStatus.
> +**/
> +CHAR8 *
> +LastAttemptStatusToString(
> +  IN UINT32 LastAttemptStatus
> +  )
> +{
> +  if (LastAttemptStatus < sizeof(mLastAttemptStatusString) /
> sizeof(mLastAttemptStatusString[0])) {
> +    return mLastAttemptStatusString[LastAttemptStatus];
> +  } else {
> +    return "Error: Unknown";
> +  }
> +}
> +
> +/**
> +  Dump ESRT entry.
> +
> +  @param EsrtEntry  ESRT entry
> +**/
> +VOID
> +DumpEsrtEntry(
> +  IN EFI_SYSTEM_RESOURCE_ENTRY  *EsrtEntry
> +  )
> +{
> +  Print(L"  FwClass                  - %g\n", &EsrtEntry->FwClass);
> +  Print(L"  FwType                   - 0x%x (%a)\n", EsrtEntry->FwType,
> FwTypeToString(EsrtEntry->FwType));
> +  Print(L"  FwVersion                - 0x%x\n", EsrtEntry->FwVersion);
> +  Print(L"  LowestSupportedFwVersion - 0x%x\n", EsrtEntry->LowestSupportedFwVersion);
> +  Print(L"  CapsuleFlags             - 0x%x\n", EsrtEntry->CapsuleFlags);
> +  Print(L"    PERSIST_ACROSS_RESET   - 0x%x\n", EsrtEntry->CapsuleFlags &
> CAPSULE_FLAGS_PERSIST_ACROSS_RESET);
> +  Print(L"    POPULATE_SYSTEM_TABLE  - 0x%x\n", EsrtEntry->CapsuleFlags &
> CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE);
> +  Print(L"    INITIATE_RESET         - 0x%x\n", EsrtEntry->CapsuleFlags &
> CAPSULE_FLAGS_INITIATE_RESET);
> +  Print(L"  LastAttemptVersion       - 0x%x\n", EsrtEntry->LastAttemptVersion);
> +  Print(L"  LastAttemptStatus        - 0x%x (%a)\n", EsrtEntry->LastAttemptStatus,
> LastAttemptStatusToString(EsrtEntry->LastAttemptStatus));
> +}
> +
> +/**
> +  Dump ESRT table.
> +
> +  @param Esrt  ESRT table
> +**/
> +VOID
> +DumpEsrt(
> +  IN EFI_SYSTEM_RESOURCE_TABLE  *Esrt
> +  )
> +{
> +  UINTN                      Index;
> +  EFI_SYSTEM_RESOURCE_ENTRY  *EsrtEntry;
> +
> +  Print(L"EFI_SYSTEM_RESOURCE_TABLE:\n");
> +  Print(L"FwResourceCount    - 0x%x\n", Esrt->FwResourceCount);
> +  Print(L"FwResourceCountMax - 0x%x\n", Esrt->FwResourceCountMax);
> +  Print(L"FwResourceVersion  - 0x%lx\n", Esrt->FwResourceVersion);
> +
> +  EsrtEntry = (VOID *)(Esrt + 1);
> +  for (Index = 0; Index < Esrt->FwResourceCount; Index++) {
> +    Print(L"EFI_SYSTEM_RESOURCE_ENTRY (%d):\n", Index);
> +    DumpEsrtEntry(EsrtEntry);
> +    EsrtEntry++;
> +  }
> +}
> +
> +/**
> +  Dump ESRT info.
> +**/
> +VOID
> +DumpEsrtData (
> +  VOID
> +  )
> +{
> +  EFI_STATUS                 Status;
> +  EFI_SYSTEM_RESOURCE_TABLE  *Esrt;
> +
> +  Print(L"##############\n");
> +  Print(L"# ESRT TABLE #\n");
> +  Print(L"##############\n");
> +
> +  Status = EfiGetSystemConfigurationTable (&gEfiSystemResourceTableGuid, (VOID
> **)&Esrt);
> +  if (EFI_ERROR(Status)) {
> +    Print(L"ESRT - %r\n", Status);
> +    return;
> +  }
> +  DumpEsrt(Esrt);
> +  Print(L"\n");
> +}
> +
> +/**
> +  Dump FMP information.
> +
> +  @param ImageInfoSize       The size of ImageInfo, in bytes.
> +  @param ImageInfo           A pointer to EFI_FIRMWARE_IMAGE_DESCRIPTOR.
> +  @param DescriptorVersion   The version of EFI_FIRMWARE_IMAGE_DESCRIPTOR.
> +  @param DescriptorCount     The count of EFI_FIRMWARE_IMAGE_DESCRIPTOR.
> +  @param DescriptorSize      The size of an individual EFI_FIRMWARE_IMAGE_DESCRIPTOR,
> in bytes.
> +  @param PackageVersion      The version of package.
> +  @param PackageVersionName  The version name of package.
> +**/
> +VOID
> +DumpFmpImageInfo(
> +  IN UINTN                           ImageInfoSize,
> +  IN EFI_FIRMWARE_IMAGE_DESCRIPTOR   *ImageInfo,
> +  IN UINT32                          DescriptorVersion,
> +  IN UINT8                           DescriptorCount,
> +  IN UINTN                           DescriptorSize,
> +  IN UINT32                          PackageVersion,
> +  IN CHAR16                          *PackageVersionName
> +  )
> +{
> +  EFI_FIRMWARE_IMAGE_DESCRIPTOR                 *CurrentImageInfo;
> +  UINTN                                         Index;
> +
> +  Print(L"  DescriptorVersion  - 0x%x\n", DescriptorVersion);
> +  Print(L"  DescriptorCount    - 0x%x\n", DescriptorCount);
> +  Print(L"  DescriptorSize     - 0x%x\n", DescriptorSize);
> +  Print(L"  PackageVersion     - 0x%x\n", PackageVersion);
> +  Print(L"  PackageVersionName - \"%s\"\n", PackageVersionName);
> +  CurrentImageInfo = ImageInfo;
> +  for (Index = 0; Index < DescriptorCount; Index++) {
> +    Print(L"  ImageDescriptor (%d)\n", Index);
> +    Print(L"    ImageIndex                  - 0x%x\n", CurrentImageInfo->ImageIndex);
> +    Print(L"    ImageTypeId                 - %g\n", &CurrentImageInfo->ImageTypeId);
> +    Print(L"    ImageId                     - 0x%lx\n", CurrentImageInfo->ImageId);
> +    Print(L"    ImageIdName                 - \"%s\"\n", CurrentImageInfo-
> >ImageIdName);
> +    Print(L"    Version                     - 0x%x\n", CurrentImageInfo->Version);
> +    Print(L"    VersionName                 - \"%s\"\n", CurrentImageInfo-
> >VersionName);
> +    Print(L"    Size                        - 0x%x\n", CurrentImageInfo->Size);
> +    Print(L"    AttributesSupported         - 0x%lx\n", CurrentImageInfo-
> >AttributesSupported);
> +    Print(L"      IMAGE_UPDATABLE           - 0x%lx\n", CurrentImageInfo-
> >AttributesSupported & IMAGE_ATTRIBUTE_IMAGE_UPDATABLE);
> +    Print(L"      RESET_REQUIRED            - 0x%lx\n", CurrentImageInfo-
> >AttributesSupported & IMAGE_ATTRIBUTE_RESET_REQUIRED);
> +    Print(L"      AUTHENTICATION_REQUIRED   - 0x%lx\n", CurrentImageInfo-
> >AttributesSupported & IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);
> +    Print(L"      IN_USE                    - 0x%lx\n", CurrentImageInfo-
> >AttributesSupported & IMAGE_ATTRIBUTE_IN_USE);
> +    Print(L"      UEFI_IMAGE                - 0x%lx\n", CurrentImageInfo-
> >AttributesSupported & IMAGE_ATTRIBUTE_UEFI_IMAGE);
> +    Print(L"    AttributesSetting           - 0x%lx\n", CurrentImageInfo-
> >AttributesSetting);
> +    Print(L"      IMAGE_UPDATABLE           - 0x%lx\n", CurrentImageInfo-
> >AttributesSetting & IMAGE_ATTRIBUTE_IMAGE_UPDATABLE);
> +    Print(L"      RESET_REQUIRED            - 0x%lx\n", CurrentImageInfo-
> >AttributesSetting & IMAGE_ATTRIBUTE_RESET_REQUIRED);
> +    Print(L"      AUTHENTICATION_REQUIRED   - 0x%lx\n", CurrentImageInfo-
> >AttributesSetting & IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);
> +    Print(L"      IN_USE                    - 0x%lx\n", CurrentImageInfo-
> >AttributesSetting & IMAGE_ATTRIBUTE_IN_USE);
> +    Print(L"      UEFI_IMAGE                - 0x%lx\n", CurrentImageInfo-
> >AttributesSetting & IMAGE_ATTRIBUTE_UEFI_IMAGE);
> +    Print(L"    Compatibilities             - 0x%lx\n", CurrentImageInfo-
> >Compatibilities);
> +    Print(L"      COMPATIB_CHECK_SUPPORTED  - 0x%lx\n", CurrentImageInfo-
> >Compatibilities & IMAGE_COMPATIBILITY_CHECK_SUPPORTED);
> +    if (DescriptorVersion > 1) {
> +      Print(L"    LowestSupportedImageVersion - 0x%x\n", CurrentImageInfo-
> >LowestSupportedImageVersion);
> +      if (DescriptorVersion > 2) {
> +        Print(L"    LastAttemptVersion          - 0x%x\n", CurrentImageInfo-
> >LastAttemptVersion);
> +        Print(L"    LastAttemptStatus           - 0x%x (%a)\n", CurrentImageInfo-
> >LastAttemptStatus, LastAttemptStatusToString(CurrentImageInfo->LastAttemptStatus));
> +        Print(L"    HardwareInstance            - 0x%lx\n", CurrentImageInfo-
> >HardwareInstance);
> +      }
> +    }
> +    //
> +    // Use DescriptorSize to move ImageInfo Pointer to stay compatible with different
> ImageInfo version
> +    //
> +    CurrentImageInfo = (EFI_FIRMWARE_IMAGE_DESCRIPTOR *)((UINT8 *)CurrentImageInfo +
> DescriptorSize);
> +  }
> +}
> +
> +/**
> +  Dump FMP package information.
> +
> +  @param PackageVersion             The version of package.
> +  @param PackageVersionName         The version name of package.
> +  @param PackageVersionNameMaxLen   The maximum length of PackageVersionName.
> +  @param AttributesSupported        Package attributes that are supported by this
> device.
> +  @param AttributesSetting          Package attributes.
> +**/
> +VOID
> +DumpFmpPackageInfo(
> +  IN UINT32                           PackageVersion,
> +  IN CHAR16                           *PackageVersionName,
> +  IN UINT32                           PackageVersionNameMaxLen,
> +  IN UINT64                           AttributesSupported,
> +  IN UINT64                           AttributesSetting
> +  )
> +{
> +  Print(L"  PackageVersion              - 0x%x\n", PackageVersion);
> +  Print(L"  PackageVersionName          - \"%s\"\n", PackageVersionName);
> +  Print(L"  PackageVersionNameMaxLen    - 0x%x\n", PackageVersionNameMaxLen);
> +  Print(L"  AttributesSupported         - 0x%lx\n", AttributesSupported);
> +  Print(L"    IMAGE_UPDATABLE           - 0x%lx\n", AttributesSupported &
> IMAGE_ATTRIBUTE_IMAGE_UPDATABLE);
> +  Print(L"    RESET_REQUIRED            - 0x%lx\n", AttributesSupported &
> IMAGE_ATTRIBUTE_RESET_REQUIRED);
> +  Print(L"    AUTHENTICATION_REQUIRED   - 0x%lx\n", AttributesSupported &
> IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);
> +  Print(L"  AttributesSetting           - 0x%lx\n", AttributesSetting);
> +  Print(L"    IMAGE_UPDATABLE           - 0x%lx\n", AttributesSetting &
> IMAGE_ATTRIBUTE_IMAGE_UPDATABLE);
> +  Print(L"    RESET_REQUIRED            - 0x%lx\n", AttributesSetting &
> IMAGE_ATTRIBUTE_RESET_REQUIRED);
> +  Print(L"    AUTHENTICATION_REQUIRED   - 0x%lx\n", AttributesSetting &
> IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);
> +}
> +
> +/**
> +  Dump FMP protocol info.
> +**/
> +VOID
> +DumpFmpData (
> +  VOID
> +  )
> +{
> +  EFI_STATUS                                    Status;
> +  EFI_FIRMWARE_MANAGEMENT_PROTOCOL              *Fmp;
> +  EFI_HANDLE                                    *HandleBuffer;
> +  UINTN                                         NumberOfHandles;
> +  UINTN                                         Index;
> +  EFI_FIRMWARE_IMAGE_DESCRIPTOR                 *FmpImageInfoBuf;
> +  UINTN                                         ImageInfoSize;
> +  UINT32                                        FmpImageInfoDescriptorVer;
> +  UINT8                                         FmpImageInfoCount;
> +  UINTN                                         DescriptorSize;
> +  UINT32                                        PackageVersion;
> +  CHAR16                                        *PackageVersionName;
> +  UINT32                                        PackageVersionNameMaxLen;
> +  UINT64                                        AttributesSupported;
> +  UINT64                                        AttributesSetting;
> +
> +  Print(L"############\n");
> +  Print(L"# FMP DATA #\n");
> +  Print(L"############\n");
> +  Status = gBS->LocateHandleBuffer (
> +                  ByProtocol,
> +                  &gEfiFirmwareManagementProtocolGuid,
> +                  NULL,
> +                  &NumberOfHandles,
> +                  &HandleBuffer
> +                  );
> +  if (EFI_ERROR(Status)) {
> +    Print(L"FMP protocol - %r\n", EFI_NOT_FOUND);
> +    return;
> +  }
> +
> +  for (Index = 0; Index < NumberOfHandles; Index++) {
> +    Status = gBS->HandleProtocol(
> +                    HandleBuffer[Index],
> +                    &gEfiFirmwareManagementProtocolGuid,
> +                    (VOID **)&Fmp
> +                    );
> +    if (EFI_ERROR(Status)) {
> +      continue;
> +    }
> +
> +    ImageInfoSize = 0;
> +    Status = Fmp->GetImageInfo (
> +                    Fmp,
> +                    &ImageInfoSize,
> +                    NULL,
> +                    NULL,
> +                    NULL,
> +                    NULL,
> +                    NULL,
> +                    NULL
> +                    );
> +    if (Status != EFI_BUFFER_TOO_SMALL) {
> +      continue;
> +    }
> +
> +    FmpImageInfoBuf = NULL;
> +    FmpImageInfoBuf = AllocateZeroPool (ImageInfoSize);
> +    if (FmpImageInfoBuf == NULL) {
> +      Status = EFI_OUT_OF_RESOURCES;
> +      goto EXIT;
> +    }
> +
> +    PackageVersionName = NULL;
> +    Status = Fmp->GetImageInfo (
> +                    Fmp,
> +                    &ImageInfoSize,               // ImageInfoSize
> +                    FmpImageInfoBuf,              // ImageInfo
> +                    &FmpImageInfoDescriptorVer,   // DescriptorVersion
> +                    &FmpImageInfoCount,           // DescriptorCount
> +                    &DescriptorSize,              // DescriptorSize
> +                    &PackageVersion,              // PackageVersion
> +                    &PackageVersionName           // PackageVersionName
> +                    );
> +
> +    //
> +    // If FMP GetInformation interface failed, skip this resource
> +    //
> +    if (EFI_ERROR(Status)) {
> +      Print(L"FMP (%d) ImageInfo - %r\n", Index, Status);
> +      FreePool(FmpImageInfoBuf);
> +      continue;
> +    }
> +
> +    Print(L"FMP (%d) ImageInfo:\n", Index);
> +    DumpFmpImageInfo(
> +      ImageInfoSize,               // ImageInfoSize
> +      FmpImageInfoBuf,             // ImageInfo
> +      FmpImageInfoDescriptorVer,   // DescriptorVersion
> +      FmpImageInfoCount,           // DescriptorCount
> +      DescriptorSize,              // DescriptorSize
> +      PackageVersion,              // PackageVersion
> +      PackageVersionName           // PackageVersionName
> +      );
> +
> +    if (PackageVersionName != NULL) {
> +      FreePool(PackageVersionName);
> +    }
> +    FreePool(FmpImageInfoBuf);
> +
> +    //
> +    // Get package info
> +    //
> +    PackageVersionName = NULL;
> +    Status = Fmp->GetPackageInfo (
> +                    Fmp,
> +                    &PackageVersion,              // PackageVersion
> +                    &PackageVersionName,          // PackageVersionName
> +                    &PackageVersionNameMaxLen,    // PackageVersionNameMaxLen
> +                    &AttributesSupported,         // AttributesSupported
> +                    &AttributesSetting            // AttributesSetting
> +                    );
> +    if (EFI_ERROR(Status)) {
> +      Print(L"FMP (%d) PackageInfo - %r\n", Index, Status);
> +    } else {
> +      Print(L"FMP (%d) ImageInfo:\n", Index);
> +      DumpFmpPackageInfo(
> +        PackageVersion,              // PackageVersion
> +        PackageVersionName,          // PackageVersionName
> +        PackageVersionNameMaxLen,    // PackageVersionNameMaxLen
> +        AttributesSupported,         // AttributesSupported
> +        AttributesSetting            // AttributesSetting
> +        );
> +
> +      if (PackageVersionName != NULL) {
> +        FreePool(PackageVersionName);
> +      }
> +    }
> +  }
> +  Print(L"\n");
> +
> +EXIT:
> +  FreePool(HandleBuffer);
> +}
> --
> 2.7.4.windows.1
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>
https://lists.01.org/mailman/listinfo/edk2-devel

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

* Re: [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application.
  2016-10-03 20:38                 ` Carsey, Jaben
@ 2016-10-11  8:08                   ` Ni, Ruiyu
  2016-10-11  8:28                     ` Ni, Ruiyu
  0 siblings, 1 reply; 83+ messages in thread
From: Ni, Ruiyu @ 2016-10-11  8:08 UTC (permalink / raw)
  To: Carsey, Jaben, Rothman, Michael A, Yao, Jiewen, Kinney, Michael D,
	edk2-devel@lists.01.org
  Cc: Tian, Feng, Zhang, Chao B, Gao, Liming, Zeng, Star

Jaben,
How about moving the contents in ShellPkg\Include\Protocol\ to MdePkg\Include\Protocol\?
All industry standard protocols are defined in MdePkg, except the Shell related protocols.

Thanks/Ray

From: Carsey, Jaben
Sent: Tuesday, October 4, 2016 4:38 AM
To: Rothman, Michael A <michael.a.rothman@intel.com>; Ni, Ruiyu <ruiyu.ni@intel.com>; Yao, Jiewen <jiewen.yao@intel.com>; Kinney, Michael D <michael.d.kinney@intel.com>; edk2-devel@lists.01.org
Cc: Tian, Feng <feng.tian@intel.com>; Zhang, Chao B <chao.b.zhang@intel.com>; Gao, Liming <liming.gao@intel.com>; Zeng, Star <star.zeng@intel.com>; Carsey, Jaben <jaben.carsey@intel.com>
Subject: RE: [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application.

I don’t think that is what I meant.  It’s a string and a length, not a structure.

I mean clarify the following:

1)      Is the name of the binary itself in the LoadOptions string as the first option or not there at all?

2)      Then clarify that all Parameters are space delimited.

From: Rothman, Michael A
Sent: Monday, October 03, 2016 11:36 AM
To: Carsey, Jaben <jaben.carsey@intel.com>; Ni, Ruiyu <ruiyu.ni@intel.com>; Yao, Jiewen <jiewen.yao@intel.com>; Kinney, Michael D <michael.d.kinney@intel.com>; edk2-devel@lists.01.org
Cc: Tian, Feng <feng.tian@intel.com>; Zhang, Chao B <chao.b.zhang@intel.com>; Gao, Liming <liming.gao@intel.com>; Zeng, Star <star.zeng@intel.com>; Rothman, Michael A <michael.a.rothman@intel.com>
Subject: RE: [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application.
Importance: High

You mean update the LoadOptions reference to refer to the EFI_LOAD_OPTION structure? Because that’s in essence what it means.

Thanks,
Mike Rothman
(迈克 罗斯曼 / माइकल रोथ्मेन् / Михаил Ротман / משה רוטמן)
רועה עיקרי של חתולים

From: Carsey, Jaben
Sent: Friday, September 30, 2016 8:31 AM
To: Ni, Ruiyu <ruiyu.ni@intel.com<mailto:ruiyu.ni@intel.com>>; Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>; edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>; Rothman, Michael A <michael.a.rothman@intel.com<mailto:michael.a.rothman@intel.com>>
Cc: Tian, Feng <feng.tian@intel.com<mailto:feng.tian@intel.com>>; Zhang, Chao B <chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com>>; Gao, Liming <liming.gao@intel.com<mailto:liming.gao@intel.com>>; Zeng, Star <star.zeng@intel.com<mailto:star.zeng@intel.com>>; Carsey, Jaben <jaben.carsey@intel.com<mailto:jaben.carsey@intel.com>>
Subject: RE: [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application.

Mike Rothman,

Can we get LoadOptions and LoadOptionsSize clarified in the UEFI Spec?  This seems like a simple clarification and I would argue its needed.  The UEFI Shell is not the only producer of this protocol.  BDS launches things (like the UEFI Shell itself) and the shell already consumes it for itself (and it works).  I think it just needs clarification so people can depend on the current implementation not changing.

-Jaben

From: Ni, Ruiyu
Sent: Thursday, September 29, 2016 9:13 PM
To: Carsey, Jaben <jaben.carsey@intel.com<mailto:jaben.carsey@intel.com>>; Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>; edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>
Cc: Tian, Feng <feng.tian@intel.com<mailto:feng.tian@intel.com>>; Zhang, Chao B <chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com>>; Gao, Liming <liming.gao@intel.com<mailto:liming.gao@intel.com>>; Zeng, Star <star.zeng@intel.com<mailto:star.zeng@intel.com>>
Subject: RE: [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application.
Importance: High

Supposing user inputs “CapsuleApp.efi Parameter1 Parameter2”.
There is no spec to define what the LoadOption should equal to.
If there is another UEFI Shell implementation, it could interpret the command line then sets only “Parameter1 Parameter2” into LoadOption, or sets “CapsuleApp.efi\tParameter1\tParameter2” to LoadOption, or sets “[Shell]\tCapsuleApp.efi\tParameter1\tParameter2” to LoadOption.
Because it“produces” such LoadOption, it knows how to “consume”/parse it to get the ARGVs.

So I suggest we put the CapsuleApp in ShellPkg and let it use the ShellParameter protocol.

Regards,
Ray

From: Carsey, Jaben
Sent: Friday, September 30, 2016 3:11 AM
To: Ni, Ruiyu <ruiyu.ni@intel.com<mailto:ruiyu.ni@intel.com>>; Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>; edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>
Cc: Tian, Feng <feng.tian@intel.com<mailto:feng.tian@intel.com>>; Zhang, Chao B <chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com>>; Gao, Liming <liming.gao@intel.com<mailto:liming.gao@intel.com>>; Zeng, Star <star.zeng@intel.com<mailto:star.zeng@intel.com>>; Carsey, Jaben <jaben.carsey@intel.com<mailto:jaben.carsey@intel.com>>
Subject: RE: [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application.

I am confused.

Why is LoadOption and LoadOptionSize not working?  This is specified as part of UEFI Spec (Note: Not UEFI Shell Spec) as a standard way to pass parameters to UEFI appliations.  I think this should work (although it is more work than just examining argc/argv).

-Jaben

From: Ni, Ruiyu
Sent: Wednesday, September 28, 2016 11:40 PM
To: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>; edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>
Cc: Tian, Feng <feng.tian@intel.com<mailto:feng.tian@intel.com>>; Zhang, Chao B <chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com>>; Gao, Liming <liming.gao@intel.com<mailto:liming.gao@intel.com>>; Zeng, Star <star.zeng@intel.com<mailto:star.zeng@intel.com>>; Carsey, Jaben <jaben.carsey@intel.com<mailto:jaben.carsey@intel.com>>
Subject: RE: [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application.
Importance: High

Jiewen,
The way CapsuleApp extracts the ARGV assumes UEFI Shell encodes the parameters using a certain way. But the parameter encoding way is not described in the Shell spec.
Maybe we can put the CapsuleApp in ShellPkg, then let it directly use ShellParameter protocol to get the ARGV.

Copying Jaben.

Regards,
Ray

From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of Yao, Jiewen
Sent: Thursday, September 29, 2016 10:37 AM
To: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>; edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>
Cc: Tian, Feng <feng.tian@intel.com<mailto:feng.tian@intel.com>>; Zhang, Chao B <chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com>>; Gao, Liming <liming.gao@intel.com<mailto:liming.gao@intel.com>>; Zeng, Star <star.zeng@intel.com<mailto:star.zeng@intel.com>>
Subject: Re: [edk2] [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application.

Right. CapsuleOnDisk is not supported in BIOS yet.
I will remove it in CapsuleApp.

CapsuleApp just works as an agent to pass capsule to CapsuleDxeRuntime driver.
So it is checked by CapsuleDxeRuntime, not CapsuleApp.

Thank you
Yao Jiewen

From: Kinney, Michael D
Sent: Thursday, September 29, 2016 9:06 AM
To: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>; Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>
Cc: Tian, Feng <feng.tian@intel.com<mailto:feng.tian@intel.com>>; Zeng, Star <star.zeng@intel.com<mailto:star.zeng@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: [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application.

Jiewen,

Does the capsule on disk feature provided by this app work?

I tried it with the QuarkPlatformPkg capsule and I can get
The app to copy the capsule to an EFI System Partition, but
The logic after that point looks incomplete.

Also, if I clear the Persist and Reset flags on the capsule,
the immediate processing of the capsule does not work.

Is there any FW code that will look for capsules on disk?

If there are incomplete features in CapsuleApp, then I think
we should remove them.

Mike

> -----Original Message-----
> From: Yao, Jiewen
> Sent: Tuesday, September 20, 2016 11:45 PM
> To: edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org%3cmailto:edk2-devel@lists.01.org>>
> Cc: Tian, Feng <feng.tian@intel.com<mailto:feng.tian@intel.com<mailto:feng.tian@intel.com%3cmailto:feng.tian@intel.com>>>; Zeng, Star <star.zeng@intel.com<mailto:star.zeng@intel.com<mailto:star.zeng@intel.com%3cmailto:star.zeng@intel.com>>>; Kinney, Michael
> D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com%3cmailto:michael.d.kinney@intel.com>>>; Gao, Liming <liming.gao@intel.com<mailto:liming.gao@intel.com<mailto:liming.gao@intel.com%3cmailto:liming.gao@intel.com>>>; Zhang, Chao B
> <chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com%3cmailto:chao.b.zhang@intel.com>>>
> Subject: [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application.
>
> This CapsuleApp can help perform capsule update in UEFI shell environment.
> It can also dump capsule information, capsule status variable, ESRT and FMP.
>
> Cc: Feng Tian <feng.tian@intel.com<mailto:feng.tian@intel.com<mailto:feng.tian@intel.com%3cmailto:feng.tian@intel.com>>>
> Cc: Star Zeng <star.zeng@intel.com<mailto:star.zeng@intel.com<mailto:star.zeng@intel.com%3cmailto:star.zeng@intel.com>>>
> Cc: Michael D Kinney <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com%3cmailto:michael.d.kinney@intel.com>>>
> Cc: Liming Gao <liming.gao@intel.com<mailto:liming.gao@intel.com<mailto:liming.gao@intel.com%3cmailto:liming.gao@intel.com>>>
> Cc: Chao Zhang <chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com%3cmailto:chao.b.zhang@intel.com>>>
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Jiewen Yao <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com<mailto:jiewen.yao@intel.com%3cmailto:jiewen.yao@intel.com>>>
> ---
>  MdeModulePkg/Application/CapsuleApp/AppSupport.c        |  480 +++++++++
>  MdeModulePkg/Application/CapsuleApp/CapsuleApp.c        | 1047 ++++++++++++++++++++
>  MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf      |   71 ++
>  MdeModulePkg/Application/CapsuleApp/CapsuleApp.uni      |   22 +
>  MdeModulePkg/Application/CapsuleApp/CapsuleAppExtra.uni |   19 +
>  MdeModulePkg/Application/CapsuleApp/CapsuleDump.c       |  840 ++++++++++++++++
>  6 files changed, 2479 insertions(+)
>
> diff --git a/MdeModulePkg/Application/CapsuleApp/AppSupport.c
> b/MdeModulePkg/Application/CapsuleApp/AppSupport.c
> new file mode 100644
> index 0000000..365067d
> --- /dev/null
> +++ b/MdeModulePkg/Application/CapsuleApp/AppSupport.c
> @@ -0,0 +1,480 @@
> +/** @file
> +  A shell application that triggers capsule update process.
> +
> +  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the BSD License
> +  which accompanies this distribution.  The full text of the license may be found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +
> +**/
> +
> +#include <Uefi.h>
> +#include <Library/BaseLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/UefiRuntimeServicesTableLib.h>
> +#include <Library/UefiLib.h>
> +#include <Library/PrintLib.h>
> +#include <Protocol/LoadedImage.h>
> +#include <Protocol/SimpleFileSystem.h>
> +#include <Guid/FileInfo.h>
> +#include <Guid/Gpt.h>
> +
> +#define MAX_ARG_NUM     11
> +
> +UINTN  Argc = 0;
> +CHAR16 *Argv[MAX_ARG_NUM];
> +CHAR16 *ArgBuffer;
> +
> +/**
> +
> +  This function parse application ARG.
> +
> +  @return Status
> +**/
> +EFI_STATUS
> +GetArg (
> +  VOID
> +  )
> +{
> +  UINT8                         *Data;
> +  UINTN                         DataSize;
> +  CHAR16                        *Index;
> +  CHAR16                        *End;
> +  CHAR16                        *DIndex;
> +  EFI_STATUS                    Status;
> +  EFI_LOADED_IMAGE_PROTOCOL     *LoadedImage;
> +
> +  Status = gBS->HandleProtocol (
> +                  gImageHandle,
> +                  &gEfiLoadedImageProtocolGuid,
> +                  (VOID**)&LoadedImage
> +                  );
> +  if (EFI_ERROR(Status)) {
> +    return Status;
> +  }
> +
> +  Data = LoadedImage->LoadOptions;
> +  DataSize = LoadedImage->LoadOptionsSize;
> +
> +  End = (CHAR16*)(UINTN)(Data + DataSize);
> +  Status = gBS->AllocatePool (EfiBootServicesData, DataSize, (VOID **)&ArgBuffer);
> +  ASSERT_EFI_ERROR (Status);
> +  DIndex = ArgBuffer;
> +  Argv[Argc++] = ArgBuffer;
> +  for (Index = (CHAR16*)Data; Index < End; ) {
> +    if (*Index == L' ') {
> +      *DIndex = L'\0';
> +      if (Argc >= MAX_ARG_NUM) {
> +        return EFI_UNSUPPORTED;
> +      }
> +      Argv[Argc++] = (++ DIndex);
> +      while(*Index == L' ') {
> +        Index ++;
> +      }
> +    }
> +    (*(DIndex ++)) = (*(Index ++));
> +  }
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Clear APP ARG.
> +**/
> +VOID
> +CleanArg (
> +  VOID
> +  )
> +{
> +  FreePool (Argv[0]);
> +}
> +
> +/**
> +  Return File System Volume containing this shell application.
> +
> +  @return File System Volume containing this shell application.
> +**/
> +EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *
> +GetMyVol (
> +  VOID
> +  )
> +{
> +  EFI_STATUS                        Status;
> +  EFI_LOADED_IMAGE_PROTOCOL         *LoadedImage;
> +  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Vol;
> +
> +  Status = gBS->HandleProtocol (
> +                  gImageHandle,
> +                  &gEfiLoadedImageProtocolGuid,
> +                  (VOID **)&LoadedImage
> +                  );
> +  ASSERT_EFI_ERROR (Status);
> +
> +  Status = gBS->HandleProtocol (
> +                  LoadedImage->DeviceHandle,
> +                  &gEfiSimpleFileSystemProtocolGuid,
> +                  (VOID **)&Vol
> +                  );
> +  if (!EFI_ERROR (Status)) {
> +    return Vol;
> +  }
> +
> +  return NULL;
> +}
> +
> +/**
> +  Read a file from this volume.
> +
> +  @param Vol             File System Volume
> +  @param FileName        The file to be read.
> +  @param BufferSize      The file buffer size
> +  @param Buffer          The file buffer
> +
> +  @retval EFI_SUCCESS    Read file successfully
> +  @retval EFI_NOT_FOUND  File not found
> +**/
> +EFI_STATUS
> +ReadFileFromVol (
> +  IN  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Vol,
> +  IN  CHAR16                            *FileName,
> +  OUT UINTN                             *BufferSize,
> +  OUT VOID                              **Buffer
> +  )
> +{
> +  EFI_STATUS                        Status;
> +  EFI_FILE_HANDLE                   RootDir;
> +  EFI_FILE_HANDLE                   Handle;
> +  UINTN                             FileInfoSize;
> +  EFI_FILE_INFO                     *FileInfo;
> +  UINTN                             TempBufferSize;
> +  VOID                              *TempBuffer;
> +
> +  //
> +  // Open the root directory
> +  //
> +  Status = Vol->OpenVolume (Vol, &RootDir);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  //
> +  // Open the file
> +  //
> +  Status = RootDir->Open (
> +                      RootDir,
> +                      &Handle,
> +                      FileName,
> +                      EFI_FILE_MODE_READ,
> +                      0
> +                      );
> +  if (EFI_ERROR (Status)) {
> +    RootDir->Close (RootDir);
> +    return Status;
> +  }
> +
> +  RootDir->Close (RootDir);
> +
> +  //
> +  // Get the file information
> +  //
> +  FileInfoSize = sizeof(EFI_FILE_INFO) + 1024;
> +
> +  FileInfo = AllocateZeroPool (FileInfoSize);
> +  if (FileInfo == NULL) {
> +    Handle->Close (Handle);
> +    return Status;
> +  }
> +
> +  Status = Handle->GetInfo (
> +                     Handle,
> +                     &gEfiFileInfoGuid,
> +                     &FileInfoSize,
> +                     FileInfo
> +                     );
> +  if (EFI_ERROR (Status)) {
> +    Handle->Close (Handle);
> +    gBS->FreePool (FileInfo);
> +    return Status;
> +  }
> +
> +  //
> +  // Allocate buffer for the file data. The last CHAR16 is for L'\0'
> +  //
> +  TempBufferSize = (UINTN) FileInfo->FileSize + sizeof(CHAR16);
> +  TempBuffer = AllocateZeroPool (TempBufferSize);
> +  if (TempBuffer == NULL) {
> +    Handle->Close (Handle);
> +    gBS->FreePool (FileInfo);
> +    return Status;
> +  }
> +
> +  gBS->FreePool (FileInfo);
> +
> +  //
> +  // Read the file data to the buffer
> +  //
> +  Status = Handle->Read (
> +                     Handle,
> +                     &TempBufferSize,
> +                     TempBuffer
> +                     );
> +  if (EFI_ERROR (Status)) {
> +    Handle->Close (Handle);
> +    gBS->FreePool (TempBuffer);
> +    return Status;
> +  }
> +
> +  Handle->Close (Handle);
> +
> +  *BufferSize = TempBufferSize;
> +  *Buffer     = TempBuffer;
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Read a file.
> +  If ScanFs is FLASE, it will use this Vol as default Fs.
> +  If ScanFs is TRUE, it will scan all FS and check the file.
> +    If there is only one file match the name, it will be read.
> +    If there is more than one file match the name, it will return Error.
> +
> +  @param ThisVol         File System Volume
> +  @param FileName        The file to be read.
> +  @param BufferSize      The file buffer size
> +  @param Buffer          The file buffer
> +  @param ScanFs          Need Scan all FS
> +
> +  @retval EFI_SUCCESS    Read file successfully
> +  @retval EFI_NOT_FOUND  File not found
> +  @retval EFI_NO_MAPPING There is duplicated files found
> +**/
> +EFI_STATUS
> +ReadFileToBufferEx (
> +  IN OUT EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   **ThisVol,
> +  IN  CHAR16                               *FileName,
> +  OUT UINTN                                *BufferSize,
> +  OUT VOID                                 **Buffer,
> +  IN  BOOLEAN                              ScanFs
> +  )
> +{
> +  EFI_STATUS                        Status;
> +  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Vol;
> +  UINTN                             TempBufferSize;
> +  VOID                              *TempBuffer;
> +  UINTN                             NoHandles;
> +  EFI_HANDLE                        *HandleBuffer;
> +  UINTN                             Index;
> +
> +  //
> +  // Check parameters
> +  //
> +  if ((FileName == NULL) || (Buffer == NULL) || (ThisVol == NULL)) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  //
> +  // not scan fs
> +  //
> +  if (!ScanFs) {
> +    if (*ThisVol == NULL) {
> +      *ThisVol = GetMyVol ();
> +      if (*ThisVol == NULL) {
> +        return EFI_INVALID_PARAMETER;
> +      }
> +    }
> +    //
> +    // Read file directly from Vol
> +    //
> +    return ReadFileFromVol (*ThisVol, FileName, BufferSize, Buffer);
> +  }
> +
> +  //
> +  // need scan fs
> +  //
> +
> +  //
> +  // Get all Vol handle
> +  //
> +  Status = gBS->LocateHandleBuffer (
> +                   ByProtocol,
> +                   &gEfiSimpleFileSystemProtocolGuid,
> +                   NULL,
> +                   &NoHandles,
> +                   &HandleBuffer
> +                   );
> +  if (EFI_ERROR (Status) && (NoHandles == 0)) {
> +    return EFI_NOT_FOUND;
> +  }
> +
> +  //
> +  // Walk through each Vol
> +  //
> +  *ThisVol = NULL;
> +  *BufferSize = 0;
> +  *Buffer     = NULL;
> +  for (Index = 0; Index < NoHandles; Index++) {
> +    Status = gBS->HandleProtocol (
> +                    HandleBuffer[Index],
> +                    &gEfiSimpleFileSystemProtocolGuid,
> +                    (VOID **)&Vol
> +                    );
> +    if (EFI_ERROR(Status)) {
> +      continue;
> +    }
> +
> +    Status = ReadFileFromVol (Vol, FileName, &TempBufferSize, &TempBuffer);
> +    if (!EFI_ERROR (Status)) {
> +      //
> +      // Read file OK, check duplication
> +      //
> +      if (*ThisVol != NULL) {
> +        //
> +        // Find the duplicated file
> +        //
> +        gBS->FreePool (TempBuffer);
> +        gBS->FreePool (*Buffer);
> +        Print (L"Duplicated FileName found!\n");
> +        return EFI_NO_MAPPING;
> +      } else {
> +        //
> +        // Record value
> +        //
> +        *ThisVol = Vol;
> +        *BufferSize = TempBufferSize;
> +        *Buffer     = TempBuffer;
> +      }
> +    }
> +  }
> +
> +  //
> +  // Scan Fs done
> +  //
> +  if (*ThisVol == NULL) {
> +    return EFI_NOT_FOUND;
> +  }
> +
> +  //
> +  // Done
> +  //
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Read a file.
> +
> +  @param FileName        The file to be read.
> +  @param BufferSize      The file buffer size
> +  @param Buffer          The file buffer
> +
> +  @retval EFI_SUCCESS    Read file successfully
> +  @retval EFI_NOT_FOUND  File not found
> +**/
> +EFI_STATUS
> +ReadFileToBuffer (
> +  IN  CHAR16                               *FileName,
> +  OUT UINTN                                *BufferSize,
> +  OUT VOID                                 **Buffer
> +  )
> +{
> +  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Vol;
> +  Vol = NULL;
> +  return ReadFileToBufferEx(&Vol, FileName, BufferSize, Buffer, FALSE);
> +}
> +
> +/**
> +  Write a file.
> +
> +  @param FileName        The file to be written.
> +  @param BufferSize      The file buffer size
> +  @param Buffer          The file buffer
> +
> +  @retval EFI_SUCCESS    Write file successfully
> +**/
> +EFI_STATUS
> +WriteFileFromBuffer(
> +  IN  CHAR16                               *FileName,
> +  IN  UINTN                                BufferSize,
> +  IN  VOID                                 *Buffer
> +  )
> +{
> +  EFI_STATUS                        Status;
> +  EFI_FILE_HANDLE                   RootDir;
> +  EFI_FILE_HANDLE                   Handle;
> +  UINTN                             TempBufferSize;
> +  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Vol;
> +
> +  Vol = GetMyVol();
> +
> +  //
> +  // Open the root directory
> +  //
> +  Status = Vol->OpenVolume (Vol, &RootDir);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  //
> +  // Open the file
> +  //
> +  Status = RootDir->Open (
> +                      RootDir,
> +                      &Handle,
> +                      FileName,
> +                      EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE| EFI_FILE_MODE_CREATE,
> +                      0
> +                      );
> +  if (EFI_ERROR (Status)) {
> +    RootDir->Close (RootDir);
> +    return Status;
> +  }
> +
> +  //
> +  // Delete file
> +  //
> +  Status = Handle->Delete(Handle);
> +  if (EFI_ERROR(Status)) {
> +    return Status;
> +  }
> +
> +  //
> +  // Open the file again
> +  //
> +  Status = RootDir->Open (
> +                      RootDir,
> +                      &Handle,
> +                      FileName,
> +                      EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE| EFI_FILE_MODE_CREATE,
> +                      0
> +                      );
> +  if (EFI_ERROR (Status)) {
> +    RootDir->Close (RootDir);
> +    return Status;
> +  }
> +
> +  RootDir->Close (RootDir);
> +
> +  //
> +  // Write the file data from the buffer
> +  //
> +  TempBufferSize = BufferSize;
> +  Status = Handle->Write (
> +                     Handle,
> +                     &TempBufferSize,
> +                     Buffer
> +                     );
> +  if (EFI_ERROR (Status)) {
> +    Handle->Close (Handle);
> +    return Status;
> +  }
> +
> +  Handle->Close (Handle);
> +
> +  return EFI_SUCCESS;
> +}
> +
> diff --git a/MdeModulePkg/Application/CapsuleApp/CapsuleApp.c
> b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.c
> new file mode 100644
> index 0000000..0a28557
> --- /dev/null
> +++ b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.c
> @@ -0,0 +1,1047 @@
> +/** @file
> +  A shell application that triggers capsule update process.
> +
> +  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the BSD License
> +  which accompanies this distribution.  The full text of the license may be found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +
> +**/
> +
> +#include <Uefi.h>
> +#include <Library/BaseLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/UefiRuntimeServicesTableLib.h>
> +#include <Library/UefiLib.h>
> +#include <Library/PrintLib.h>
> +#include <Protocol/LoadedImage.h>
> +#include <Protocol/SimpleFileSystem.h>
> +#include <Protocol/GraphicsOutput.h>
> +#include <Guid/FileInfo.h>
> +#include <Guid/Gpt.h>
> +#include <Guid/GlobalVariable.h>
> +#include <Guid/CapsuleReport.h>
> +#include <Guid/SystemResourceTable.h>
> +#include <Guid/FmpCapsule.h>
> +#include <IndustryStandard/WindowsUxCapsule.h>
> +
> +#define CAPSULE_HEADER_SIZE  0x20
> +
> +#define NESTED_CAPSULE_HEADER_SIZE  SIZE_4KB
> +#define SYSTEM_FIRMWARE_FLAG 0x50000
> +#define DEVICE_FIRMWARE_FLAG 0x78010
> +
> +#define EFI_CAPSULE_FROM_FILE_DIR                           L"\\EFI\\UpdateCapsule\\<file:///\\EFI\UpdateCapsule\><file://EFI/UpdateCapsule/%3cfile:/EFI/UpdateCapsule/%3e>"
> +#define EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED  0x0000000000000004
> +
> +#define MAJOR_VERSION   1
> +#define MINOR_VERSION   0
> +
> +#define MAX_ARG_NUM     11
> +#define MAX_CAPSULE_NUM (MAX_ARG_NUM - 1)
> +
> +extern UINTN  Argc;
> +extern CHAR16 *Argv[];
> +
> +//
> +// Define how many block descriptors we want to test with.
> +//
> +UINTN  NumberOfDescriptors = 1;
> +UINTN  CapsuleFirstIndex;
> +UINTN  CapsuleLastIndex;
> +
> +/**
> +  Dump capsule information
> +
> +  @retval EFI_SUCCESS            The capsule information is dumped.
> +  @retval EFI_UNSUPPORTED        Input parameter is not valid.
> +**/
> +EFI_STATUS
> +DumpCapsule(
> +  VOID
> +  );
> +
> +/**
> +  Dump capsule status variable.
> +
> +  @retval EFI_SUCCESS            The capsule status variable is dumped.
> +  @retval EFI_UNSUPPORTED        Input parameter is not valid.
> +**/
> +EFI_STATUS
> +DmpCapsuleStatusVariable(
> +  VOID
> +  );
> +
> +/**
> +  Dump FMP protocol info.
> +**/
> +VOID
> +DumpFmpData(
> +  VOID
> +  );
> +
> +/**
> +  Dump ESRT info.
> +**/
> +VOID
> +DumpEsrtData(
> +  VOID
> +  );
> +
> +/**
> +  Read a file.
> +
> +  @param FileName        The file to be read.
> +  @param BufferSize      The file buffer size
> +  @param Buffer          The file buffer
> +
> +  @retval EFI_SUCCESS    Read file successfully
> +  @retval EFI_NOT_FOUND  File not found
> +**/
> +EFI_STATUS
> +ReadFileToBuffer(
> +  IN  CHAR16                               *FileName,
> +  OUT UINTN                                *BufferSize,
> +  OUT VOID                                 **Buffer
> +  );
> +
> +/**
> +  Write a file.
> +
> +  @param FileName        The file to be written.
> +  @param BufferSize      The file buffer size
> +  @param Buffer          The file buffer
> +
> +  @retval EFI_SUCCESS    Write file successfully
> +**/
> +EFI_STATUS
> +WriteFileFromBuffer(
> +  IN  CHAR16                               *FileName,
> +  IN  UINTN                                BufferSize,
> +  IN  VOID                                 *Buffer
> +  );
> +
> +/**
> +
> +  This function parse application ARG.
> +
> +  @return Status
> +**/
> +EFI_STATUS
> +GetArg (
> +  VOID
> +  );
> +
> +/**
> +  Clear APP ARG.
> +**/
> +VOID
> +CleanArg (
> +  VOID
> +  );
> +
> +/**
> +  Create UX capsule.
> +
> +  @retval EFI_SUCCESS            The capsule header is appended.
> +  @retval EFI_UNSUPPORTED        Input parameter is not valid.
> +  @retval EFI_OUT_OF_RESOURCES   No enough resource to create UX capsule.
> +**/
> +EFI_STATUS
> +CreateBmpFmp(
> +  VOID
> +  )
> +{
> +  CHAR16                                        *OutputCapsuleName;
> +  VOID                                          *BmpBuffer;
> +  UINTN                                         FileSize;
> +  CHAR16                                        *BmpName;
> +  UINT8                                         *FullCapsuleBuffer;
> +  UINTN                                         FullCapsuleBufferSize;
> +  EFI_DISPLAY_CAPSULE                           *DisplayCapsule;
> +  EFI_STATUS                                    Status;
> +  EFI_GRAPHICS_OUTPUT_PROTOCOL                  *Gop;
> +
> +  Status = gBS->LocateProtocol(&gEfiGraphicsOutputProtocolGuid, NULL, (VOID **)&Gop);
> +  if (EFI_ERROR(Status)) {
> +    Print(L"CapsuleApp: NO GOP is found.\n");
> +    return EFI_UNSUPPORTED;
> +  }
> +  Print(L"Current GOP: Mode - %d, ", Gop->Mode->Mode);
> +  Print(L"HorizontalResolution - %d, ", Gop->Mode->Info->HorizontalResolution);
> +  Print(L"VerticalResolution - %d\n", Gop->Mode->Info->VerticalResolution);
> +  // HorizontalResolution >= BMP_IMAGE_HEADER.PixelWidth
> +  // VerticalResolution   >= BMP_IMAGE_HEADER.PixelHeight
> +
> +  if (Argc != 5) {
> +    Print(L"CapsuleApp: Invalid Parameter.\n");
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  if (StrCmp(Argv[3], L"-O") != 0) {
> +    Print(L"CapsuleApp: NO output capsule name.\n");
> +    return EFI_UNSUPPORTED;
> +  }
> +  OutputCapsuleName = Argv[4];
> +
> +  BmpBuffer = NULL;
> +  FileSize = 0;
> +  FullCapsuleBuffer = NULL;
> +
> +  BmpName = Argv[2];
> +  Status = ReadFileToBuffer(BmpName, &FileSize, &BmpBuffer);
> +  if (EFI_ERROR(Status)) {
> +    Print(L"CapsuleApp: BMP image (%s) is not found.\n", BmpName);
> +    goto Done;
> +  }
> +
> +  FullCapsuleBufferSize = sizeof(EFI_DISPLAY_CAPSULE) + FileSize;
> +  FullCapsuleBuffer = AllocatePool(FullCapsuleBufferSize);
> +  if (FullCapsuleBuffer == NULL) {
> +    Print(L"CapsuleApp: Capsule Buffer size (0x%x) too big.\n",
> FullCapsuleBufferSize);
> +    Status = EFI_OUT_OF_RESOURCES;
> +    goto Done;
> +  }
> +
> +  DisplayCapsule = (EFI_DISPLAY_CAPSULE *)FullCapsuleBuffer;
> +  CopyGuid(&DisplayCapsule->CapsuleHeader.CapsuleGuid, &gWindowsUxCapsuleGuid);
> +  DisplayCapsule->CapsuleHeader.HeaderSize = sizeof(DisplayCapsule->CapsuleHeader);
> +  DisplayCapsule->CapsuleHeader.Flags = CAPSULE_FLAGS_PERSIST_ACROSS_RESET;
> +  DisplayCapsule->CapsuleHeader.CapsuleImageSize = (UINT32)FullCapsuleBufferSize;
> +
> +  DisplayCapsule->ImagePayload.Version = 1;
> +  DisplayCapsule->ImagePayload.Checksum = 0;
> +  DisplayCapsule->ImagePayload.ImageType = 0; // BMP
> +  DisplayCapsule->ImagePayload.Reserved = 0;
> +  DisplayCapsule->ImagePayload.Mode = Gop->Mode->Mode;
> +  DisplayCapsule->ImagePayload.OffsetX = 0;
> +  DisplayCapsule->ImagePayload.OffsetY = 0;
> +
> +  CopyMem((DisplayCapsule + 1), BmpBuffer, FileSize);
> +
> +  DisplayCapsule->ImagePayload.Checksum = CalculateCheckSum8(FullCapsuleBuffer,
> FullCapsuleBufferSize);
> +
> +  Status = WriteFileFromBuffer(OutputCapsuleName, FullCapsuleBufferSize,
> FullCapsuleBuffer);
> +  Print(L"CapsuleApp: Write %s %r\n", OutputCapsuleName, Status);
> +
> +Done:
> +  if (BmpBuffer != NULL) {
> +    FreePool(BmpBuffer);
> +  }
> +
> +  if (FullCapsuleBuffer != NULL) {
> +    FreePool(FullCapsuleBuffer);
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  Get ImageTypeId in the FMP capsule header.
> +
> +  @param CapsuleHeader  The FMP capsule image header.
> +
> +  @return ImageTypeId
> +**/
> +EFI_GUID *
> +GetCapsuleImageTypeId(
> +  IN EFI_CAPSULE_HEADER                            *CapsuleHeader
> +  )
> +{
> +  EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER       *FmpCapsuleHeader;
> +  UINT64                                       *ItemOffsetList;
> +  EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader;
> +
> +  FmpCapsuleHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *)((UINT8 *)CapsuleHeader
> + CapsuleHeader->HeaderSize);
> +  ItemOffsetList = (UINT64 *)(FmpCapsuleHeader + 1);
> +  if (FmpCapsuleHeader->PayloadItemCount == 0) {
> +    return NULL;
> +  }
> +  ImageHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *)((UINT8
> *)FmpCapsuleHeader + ItemOffsetList[FmpCapsuleHeader->EmbeddedDriverCount]);
> +  return &ImageHeader->UpdateImageTypeId;
> +}
> +
> +/**
> +  Get ESRT FwType according to ImageTypeId
> +
> +  @param  ImageTypeId   ImageTypeId of an FMP capsule.
> +
> +  @return ESRT FwType
> +**/
> +UINT32
> +GetEsrtFwType(
> +  IN  EFI_GUID                                      *ImageTypeId
> +  )
> +{
> +  EFI_STATUS                 Status;
> +  EFI_SYSTEM_RESOURCE_TABLE  *Esrt;
> +  EFI_SYSTEM_RESOURCE_ENTRY  *EsrtEntry;
> +  UINTN                      Index;
> +
> +  //
> +  // Check ESRT
> +  //
> +  Status = EfiGetSystemConfigurationTable(&gEfiSystemResourceTableGuid, (VOID
> **)&Esrt);
> +  if (!EFI_ERROR(Status)) {
> +    EsrtEntry = (VOID *)(Esrt + 1);
> +    for (Index = 0; Index < Esrt->FwResourceCount; Index++, EsrtEntry++) {
> +      if (CompareGuid(&EsrtEntry->FwClass, ImageTypeId)) {
> +        return EsrtEntry->FwType;
> +      }
> +    }
> +  }
> +
> +  return ESRT_FW_TYPE_UNKNOWN;
> +}
> +
> +/**
> +  Append a capsule header on top of current image.
> +  This function follows Windows UEFI Firmware Update Platform document.
> +
> +  @retval EFI_SUCCESS            The capsule header is appended.
> +  @retval EFI_UNSUPPORTED        Input parameter is not valid.
> +  @retval EFI_OUT_OF_RESOURCES   No enough resource to append capsule header.
> +**/
> +EFI_STATUS
> +CreateNestedFmp(
> +  VOID
> +  )
> +{
> +  CHAR16                                        *OutputCapsuleName;
> +  VOID                                          *CapsuleBuffer;
> +  UINTN                                         FileSize;
> +  CHAR16                                        *CapsuleName;
> +  UINT8                                         *FullCapsuleBuffer;
> +  UINTN                                         FullCapsuleBufferSize;
> +  EFI_CAPSULE_HEADER                            *NestedCapsuleHeader;
> +  EFI_GUID                                      *ImageTypeId;
> +  UINT32                                        FwType;
> +  EFI_STATUS                                    Status;
> +
> +  if (Argc != 5) {
> +    Print(L"CapsuleApp: Invalid Parameter.\n");
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  if (StrCmp(Argv[3], L"-O") != 0) {
> +    Print(L"CapsuleApp: NO output capsule name.\n");
> +    return EFI_UNSUPPORTED;
> +  }
> +  OutputCapsuleName = Argv[4];
> +
> +  CapsuleBuffer = NULL;
> +  FileSize = 0;
> +  FullCapsuleBuffer = NULL;
> +
> +  CapsuleName = Argv[2];
> +  Status = ReadFileToBuffer(CapsuleName, &FileSize, &CapsuleBuffer);
> +  if (EFI_ERROR(Status)) {
> +    Print(L"CapsuleApp: Capsule image (%s) is not found.\n", CapsuleName);
> +    goto Done;
> +  }
> +
> +  ImageTypeId = GetCapsuleImageTypeId(CapsuleBuffer);
> +  if (ImageTypeId == NULL) {
> +    Print(L"CapsuleApp: Capsule ImageTypeId is not found.\n");
> +    goto Done;
> +  }
> +  FwType = GetEsrtFwType(ImageTypeId);
> +  if ((FwType != ESRT_FW_TYPE_SYSTEMFIRMWARE) && (FwType !=
> ESRT_FW_TYPE_DEVICEFIRMWARE)) {
> +    Print(L"CapsuleApp: Capsule FwType is invalid.\n");
> +    goto Done;
> +  }
> +
> +  FullCapsuleBufferSize = NESTED_CAPSULE_HEADER_SIZE + FileSize;
> +  FullCapsuleBuffer = AllocatePool(FullCapsuleBufferSize);
> +  if (FullCapsuleBuffer == NULL) {
> +    Print(L"CapsuleApp: Capsule Buffer size (0x%x) too big.\n",
> FullCapsuleBufferSize);
> +    Status = EFI_OUT_OF_RESOURCES;
> +    goto Done;
> +  }
> +
> +  NestedCapsuleHeader = (EFI_CAPSULE_HEADER *)FullCapsuleBuffer;
> +  ZeroMem(NestedCapsuleHeader, NESTED_CAPSULE_HEADER_SIZE);
> +  CopyGuid(&NestedCapsuleHeader->CapsuleGuid, ImageTypeId);
> +  NestedCapsuleHeader->HeaderSize = NESTED_CAPSULE_HEADER_SIZE;
> +  NestedCapsuleHeader->Flags = (FwType == ESRT_FW_TYPE_DEVICEFIRMWARE) ?
> SYSTEM_FIRMWARE_FLAG : DEVICE_FIRMWARE_FLAG;
> +  NestedCapsuleHeader->CapsuleImageSize = (UINT32)FullCapsuleBufferSize;
> +
> +  CopyMem((UINT8 *)NestedCapsuleHeader + NestedCapsuleHeader->HeaderSize,
> CapsuleBuffer, FileSize);
> +
> +  Status = WriteFileFromBuffer(OutputCapsuleName, FullCapsuleBufferSize,
> FullCapsuleBuffer);
> +  Print(L"CapsuleApp: Write %s %r\n", OutputCapsuleName, Status);
> +
> +Done:
> +  if (CapsuleBuffer != NULL) {
> +    FreePool(CapsuleBuffer);
> +  }
> +
> +  if (FullCapsuleBuffer != NULL) {
> +    FreePool(FullCapsuleBuffer);
> +  }
> +
> +  return Status;
> +}
> +
> +
> +/**
> +  Clear capsule status variable.
> +
> +  @retval EFI_SUCCESS            The capsule status variable is cleared.
> +**/
> +EFI_STATUS
> +ClearCapsuleStatusVariable(
> +  VOID
> +  )
> +{
> +  EFI_STATUS                          Status;
> +  UINT32                              Index;
> +  CHAR16                              CapsuleVarName[20];
> +  CHAR16                              *TempVarName;
> +
> +  StrCpyS (CapsuleVarName, sizeof(CapsuleVarName)/sizeof(CapsuleVarName[0]),
> L"Capsule");
> +  TempVarName = CapsuleVarName + StrLen (CapsuleVarName);
> +  Index = 0;
> +
> +  while (TRUE) {
> +    UnicodeSPrint (TempVarName, 5 * sizeof(CHAR16), L"%04x", Index);
> +
> +    Status = gRT->SetVariable (
> +                    CapsuleVarName,
> +                    &gEfiCapsuleReportGuid,
> +                    EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS |
> EFI_VARIABLE_BOOTSERVICE_ACCESS,
> +                    0,
> +                    (VOID *)NULL
> +                    );
> +    if (EFI_ERROR(Status)) {
> +      //
> +      // There is no capsule variables, quit
> +      //
> +      break;
> +    }
> +
> +    Index++;
> +    if (Index > 0xFFFF) {
> +      break;
> +    }
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Get the active UEFI system partition from bootoption list.
> +
> +  @param[out] Fs    Simple File System protocol on the active UEFI system partition
> +
> +  @retval EFI_SUCCESS   active UEFI system partition found
> +**/
> +EFI_STATUS
> +GetEfiSysPartition(
> +  OUT EFI_SIMPLE_FILE_SYSTEM_PROTOCOL **Fs
> +  )
> +{
> +  EFI_STATUS                       Status;
> +  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL  *FsTemp;
> +  UINTN                            NoHandles;
> +  EFI_HANDLE                       *Handles;
> +  UINTN                            Index;
> +
> +  Handles = NULL;
> +
> +  //
> +  // search for EFI system partition protocol on Boot option device path
> +  //
> +  Status = gBS->LocateHandleBuffer(ByProtocol, &gEfiPartTypeSystemPartGuid, NULL,
> &NoHandles, &Handles);
> +  if (EFI_ERROR(Status)) {
> +    return Status;
> +  }
> +
> +  //
> +  // Skip BootOptions within FV
> +  //
> +  for (Index = 0; Index < NoHandles; Index++) {
> +    Status = gBS->HandleProtocol (Handles[Index], &gEfiSimpleFileSystemProtocolGuid,
> (VOID **)&FsTemp);
> +    if (!EFI_ERROR (Status)){
> +      *Fs = FsTemp;
> +      break;
> +    }
> +  }
> +  return Status;
> +}
> +
> +/**
> +  Copy a list of capsule images to the active UEFI system partition from bootoption
> list.
> +
> +  @param[in] CapsuleBuffer    An array of pointer to capsule images
> +  @param[in] FileSize         An array of UINTN to capsule images size
> +  @param[in] CapsuleNum       The count of capsule images
> +
> +  @retval EFI_SUCCESS   Capsule images are copied to the active UEFI system partition
> +**/
> +EFI_STATUS
> +CopyCapsuleToActiveEfiPartition(
> +  IN VOID                          **CapsuleBuffer,
> +  IN UINTN                         *FileSize,
> +  IN UINTN                         CapsuleNum
> +  )
> +{
> +  EFI_STATUS                       Status;
> +  CHAR16                           *CapsuleName;
> +  UINTN                            Index;
> +  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL  *Fs;
> +  EFI_FILE_HANDLE                  RootDir;
> +  EFI_FILE_HANDLE                  CapsuleDir;
> +  EFI_FILE_HANDLE                  DestHandle;
> +  UINTN                            DataSize;
> +  UINT64                           OsIndication;
> +
> +  RootDir      = NULL;
> +  CapsuleDir   = NULL;
> +
> +  Status = GetEfiSysPartition(&Fs);
> +  if (EFI_ERROR(Status)) {
> +    Print (L"Can not find active UEFI System Partition\n");
> +    return Status;
> +  }
> +
> +  Status = Fs->OpenVolume(Fs, &RootDir);
> +  if (EFI_ERROR(Status)) {
> +    goto EXIT;
> +  }
> +
> +  Status = RootDir->Open(
> +                      RootDir,
> +                      &CapsuleDir,
> +                      EFI_CAPSULE_FROM_FILE_DIR,
> +                      EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE,
> +                      EFI_FILE_DIRECTORY
> +                      );
> +  if (EFI_ERROR(Status)) {
> +    goto EXIT;
> +  }
> +
> +  //
> +  // Read the input files.
> +  //
> +  for (Index = 0; Index < CapsuleNum; Index++) {
> +    CapsuleName = Argv[CapsuleFirstIndex + Index];
> +    Status = CapsuleDir->Open(
> +                           CapsuleDir,
> +                           &DestHandle,
> +                           CapsuleName,
> +                           EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE |
> EFI_FILE_MODE_CREATE,
> +                           EFI_FILE_ARCHIVE
> +                           );
> +    if (EFI_ERROR(Status)) {
> +      Print(L"CapsuleApp: %s open error - %r\n", CapsuleName, Status);
> +      continue;
> +    }
> +
> +    DataSize = FileSize[Index];
> +    Status = DestHandle->Write(
> +                           DestHandle,
> +                           &DataSize,
> +                           CapsuleBuffer[Index]
> +                           );
> +    DestHandle->Close(DestHandle);
> +    if (EFI_ERROR(Status)) {
> +      Print(L"CapsuleApp: %s write error - %r, FileSize - 0x%x\n", CapsuleName,
> Status, FileSize[Index]);
> +    }
> +  }
> +
> +  Status = gRT->GetVariable (
> +                  L"OsIndications",
> +                  &gEfiGlobalVariableGuid,
> +                  NULL,
> +                  &DataSize,
> +                  (VOID *) &OsIndication
> +                  );
> +
> +  if (EFI_ERROR(Status) || DataSize != sizeof(OsIndication)) {
> +    OsIndication = 0;
> +  }
> +
> +  //
> +  // Set OsIndications Variable EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED bit
> +  //
> +  OsIndication |= EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED;
> +  Status = gRT->SetVariable (
> +                  L"OsIndications",
> +                  &gEfiGlobalVariableGuid,
> +                  EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS |
> +                  EFI_VARIABLE_BOOTSERVICE_ACCESS,
> +                  sizeof(OsIndication),
> +                  (VOID *)&OsIndication
> +                  );
> +
> +
> +EXIT:
> +  if (RootDir != NULL) {
> +    RootDir->Close(RootDir);
> +  }
> +
> +  if (CapsuleDir != NULL) {
> +    CapsuleDir->Close(CapsuleDir);
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  Build Gather list for a list of capsule images.
> +
> +  @param[in]  CapsuleBuffer    An array of pointer to capsule images
> +  @param[in]  FileSize         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                         *FileSize,
> +  IN UINTN                         CapsuleNum,
> +  OUT EFI_CAPSULE_BLOCK_DESCRIPTOR **BlockDescriptors
> +  )
> +{
> +  EFI_STATUS                    Status;
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR  *BlockDescriptors1;
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR  *BlockDescriptors2;
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR  *BlockDescriptorPre;
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR  *BlockDescriptorsHeader;
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR  *TempBlockPtr;
> +  UINT8                         *TempDataPtr;
> +  UINTN                         SizeLeft;
> +  UINTN                         Size;
> +  INT32                         Count;
> +  INT32                         Number;
> +  UINTN                         Index;
> +
> +  TempBlockPtr           = NULL;
> +  BlockDescriptors1      = NULL;
> +  BlockDescriptors2      = NULL;
> +  BlockDescriptorPre     = NULL;
> +  BlockDescriptorsHeader = NULL;
> +
> +  for (Index = 0; Index < CapsuleNum; Index++) {
> +    //
> +    // Allocate memory for the descriptors.
> +    //
> +    if (NumberOfDescriptors == 1) {
> +      Count = 2;
> +    } else {
> +      Count = (INT32)(NumberOfDescriptors + 2) / 2;
> +    }
> +
> +    Size               = Count * sizeof (EFI_CAPSULE_BLOCK_DESCRIPTOR);
> +    BlockDescriptors1  = AllocateRuntimeZeroPool (Size);
> +    if (BlockDescriptors1 == NULL) {
> +      Print (L"CapsuleApp: failed to allocate memory for descriptors\n");
> +      Status = EFI_OUT_OF_RESOURCES;
> +      goto ERREXIT;
> +    } else {
> +      Print (L"CapsuleApp: creating capsule descriptors at 0x%X\n", (UINTN)
> BlockDescriptors1);
> +      Print (L"CapsuleApp: capsule data starts          at 0x%X with size 0x%X\n",
> (UINTN) CapsuleBuffer, FileSize);
> +    }
> +
> +    //
> +    // Record descirptor header
> +    //
> +    if (Index == 0) {
> +      BlockDescriptorsHeader = BlockDescriptors1;
> +    }
> +
> +    if (BlockDescriptorPre != NULL) {
> +      BlockDescriptorPre->Union.ContinuationPointer = (UINTN) BlockDescriptors1;
> +      BlockDescriptorPre->Length = 0;
> +    }
> +
> +    //
> +    // Fill them in
> +    //
> +    TempBlockPtr  = BlockDescriptors1;
> +    TempDataPtr   = CapsuleBuffer[Index];
> +    SizeLeft      = FileSize[Index];
> +    for (Number = 0; (Number < Count - 1) && (SizeLeft != 0); Number++) {
> +      //
> +      // Divide remaining data in half
> +      //
> +      if (NumberOfDescriptors != 1) {
> +        if (SizeLeft == 1) {
> +          Size = 1;
> +        } else {
> +          Size = SizeLeft / 2;
> +        }
> +      } else {
> +        Size = SizeLeft;
> +      }
> +      TempBlockPtr->Union.DataBlock    = (UINTN)TempDataPtr;
> +      TempBlockPtr->Length  = Size;
> +      Print (L"CapsuleApp: capsule block/size              0x%X/0x%X\n", (UINTN)
> TempDataPtr, Size);
> +      SizeLeft -= Size;
> +      TempDataPtr += Size;
> +      TempBlockPtr++;
> +    }
> +
> +    //
> +    // Allocate the second list, point the first block's last entry to point
> +    // to this one, and fill this one in. Worst case is that the previous
> +    // list only had one element that pointed here, so we need at least two
> +    // elements -- one to point to all the data, another to terminate the list.
> +    //
> +    if ((NumberOfDescriptors != 1) && (SizeLeft != 0)) {
> +      Count = (INT32)(NumberOfDescriptors + 2) - Count;
> +      if (Count == 1) {
> +        Count++;
> +      }
> +
> +      Size              = Count * sizeof (EFI_CAPSULE_BLOCK_DESCRIPTOR);
> +      BlockDescriptors2 = AllocateRuntimeZeroPool (Size);
> +      if (BlockDescriptors2 == NULL) {
> +        Print (L"CapsuleApp: failed to allocate memory for descriptors\n");
> +        Status = EFI_OUT_OF_RESOURCES;
> +        goto ERREXIT;
> +      }
> +
> +      //
> +      // Point the first list's last element to point to this second list.
> +      //
> +      TempBlockPtr->Union.ContinuationPointer   = (UINTN) BlockDescriptors2;
> +
> +      TempBlockPtr->Length  = 0;
> +      TempBlockPtr = BlockDescriptors2;
> +      for (Number = 0; Number < Count - 1; Number++) {
> +        //
> +        // If second-to-last one, then dump rest to this element
> +        //
> +        if (Number == (Count - 2)) {
> +          Size = SizeLeft;
> +        } else {
> +          //
> +          // Divide remaining data in half
> +          //
> +          if (SizeLeft == 1) {
> +            Size = 1;
> +          } else {
> +            Size = SizeLeft / 2;
> +          }
> +        }
> +
> +        TempBlockPtr->Union.DataBlock    = (UINTN)TempDataPtr;
> +        TempBlockPtr->Length  = Size;
> +        Print (L"CapsuleApp: capsule block/size              0x%X/0x%X\n", (UINTN)
> TempDataPtr, Size);
> +        SizeLeft -= Size;
> +        TempDataPtr += Size;
> +        TempBlockPtr++;
> +        if (SizeLeft == 0) {
> +          break;
> +        }
> +      }
> +    }
> +
> +    BlockDescriptorPre = TempBlockPtr;
> +    BlockDescriptors1  = NULL;
> +  }
> +
> +  //
> +  // Null-terminate.
> +  //
> +  if (TempBlockPtr != NULL) {
> +    TempBlockPtr->Union.ContinuationPointer    = (UINTN)NULL;
> +    TempBlockPtr->Length  = 0;
> +    *BlockDescriptors = BlockDescriptorsHeader;
> +  }
> +
> +  return EFI_SUCCESS;
> +
> +ERREXIT:
> +  if (BlockDescriptors1 != NULL) {
> +    FreePool(BlockDescriptors1);
> +  }
> +
> +  if (BlockDescriptors2 != NULL) {
> +    FreePool(BlockDescriptors2);
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  Clear the Gather list for a list of capsule images.
> +
> +  @param[in]  BlockDescriptors The block descriptors for the capsule images
> +  @param[in]  CapsuleNum       The count of capsule images
> +**/
> +VOID
> +CleanGatherList(
> +  IN EFI_CAPSULE_BLOCK_DESCRIPTOR   *BlockDescriptors,
> +  IN UINTN                          CapsuleNum
> +  )
> +{
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR   *TempBlockPtr;
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR   *TempBlockPtr1;
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR   *TempBlockPtr2;
> +  UINTN                          Index;
> +
> +  if (BlockDescriptors != NULL) {
> +    TempBlockPtr1 = BlockDescriptors;
> +    while (1){
> +      TempBlockPtr = TempBlockPtr1;
> +      for (Index = 0; Index < CapsuleNum; Index++) {
> +        if (TempBlockPtr[Index].Length == 0) {
> +          break;
> +        }
> +      }
> +
> +      if (TempBlockPtr[Index].Union.ContinuationPointer == (UINTN)NULL) {
> +        break;
> +      }
> +
> +      TempBlockPtr2 = (VOID *) ((UINTN) TempBlockPtr->Union.ContinuationPointer);
> +      FreePool(TempBlockPtr1);
> +      TempBlockPtr1 = TempBlockPtr2;
> +    }
> +  }
> +}
> +
> +/**
> +  Print APP usage.
> +**/
> +VOID
> +PrintUsage (
> +  VOID
> +  )
> +{
> +  Print(L"CapsuleApp:  usage\n");
> +  Print(L"  CapsuleApp [-F] <Capsule...> [-NR]\n");
> +  Print(L"  CapsuleApp -S\n");
> +  Print(L"  CapsuleApp -C\n");
> +  Print(L"  CapsuleApp -P\n");
> +  Print(L"  CapsuleApp -E\n");
> +  Print(L"  CapsuleApp -G <BMP> -O <Capsule>\n");
> +  Print(L"  CapsuleApp -N <Capsule> -O <NestedCapsule>\n");
> +  Print(L"  CapsuleApp -D|-DS <Capsule>\n");
> +  Print(L"Parameter:\n");
> +  Print(L"  -F:  Put capsule file to disk.\n");
> +  Print(L"       No -F means to put capsule file in memory.\n");
> +  Print(L"  -NR: No Reset.\n");
> +  Print(L"  -S:  Dump capsule status.\n");
> +  Print(L"  -C:  Clear capsule status.\n");
> +  Print(L"  -P:  Dump FMP protocol info.\n");
> +  Print(L"  -E:  Dump ESRT table info.\n");
> +  Print(L"  -G:  Input BMP file name\n");
> +  Print(L"  -N:  Append Capsule Header accroding to Windows Firmware Update\n");
> +  Print(L"  -O:  Output Capsule file name\n");
> +  Print(L"  -D:  Dump Capsule\n");
> +  Print(L"  -DS: Dump Capsule with System FMP format\n");
> +}
> +
> +/**
> +  Update Capsule image.
> +
> +  @param[in]  ImageHandle     The image handle.
> +  @param[in]  SystemTable     The system table.
> +
> +  @retval EFI_SUCCESS            Command completed successfully.
> +  @retval EFI_INVALID_PARAMETER  Command usage error.
> +  @retval EFI_NOT_FOUND          The input file can't be found.
> +**/
> +EFI_STATUS
> +EFIAPI
> +UefiMain (
> +  IN EFI_HANDLE        ImageHandle,
> +  IN EFI_SYSTEM_TABLE  *SystemTable
> +  )
> +{
> +  EFI_STATUS                    Status;
> +  UINTN                         FileSize[MAX_CAPSULE_NUM];
> +  VOID                          *CapsuleBuffer[MAX_CAPSULE_NUM];
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR  *BlockDescriptors;
> +  EFI_CAPSULE_HEADER             *CapsuleHeaderArray[MAX_CAPSULE_NUM + 1];
> +  UINT64                         MaxCapsuleSize;
> +  EFI_RESET_TYPE                 ResetType;
> +  BOOLEAN                        NeedReset;
> +  BOOLEAN                        NoReset;
> +  BOOLEAN                        NeedCopyOnDisk;
> +  CHAR16                         *CapsuleName;
> +  UINTN                          CapsuleNum;
> +  UINTN                          Index;
> +
> +  Status = GetArg();
> +  if (EFI_ERROR(Status)) {
> +    PrintUsage();
> +    return Status;
> +  }
> +  if (Argc < 2) {
> +    PrintUsage();
> +    CleanArg();
> +    return EFI_INVALID_PARAMETER;
> +  }
> +  if ((StrCmp(Argv[1], L"-D") == 0) ||
> +      (StrCmp(Argv[1], L"-DS") == 0)) {
> +    Status = DumpCapsule();
> +    CleanArg();
> +    return Status;
> +  }
> +  if (StrCmp(Argv[1], L"-G") == 0) {
> +    Status = CreateBmpFmp();
> +    CleanArg();
> +    return Status;
> +  }
> +  if (StrCmp(Argv[1], L"-N") == 0) {
> +    Status = CreateNestedFmp();
> +    CleanArg();
> +    return Status;
> +  }
> +  if (StrCmp(Argv[1], L"-S") == 0) {
> +    Status = DmpCapsuleStatusVariable();
> +    CleanArg();
> +    return EFI_SUCCESS;
> +  }
> +  if (StrCmp(Argv[1], L"-C") == 0) {
> +    Status = ClearCapsuleStatusVariable();
> +    CleanArg();
> +    return Status;
> +  }
> +  if (StrCmp(Argv[1], L"-P") == 0) {
> +    DumpFmpData();
> +    CleanArg();
> +    return EFI_SUCCESS;
> +  }
> +  if (StrCmp(Argv[1], L"-E") == 0) {
> +    DumpEsrtData();
> +    CleanArg();
> +    return EFI_SUCCESS;
> +  }
> +  if (StrCmp(Argv[1], L"-F") == 0) {
> +    NeedCopyOnDisk = TRUE;
> +    CapsuleFirstIndex = 2;
> +  } else {
> +    NeedCopyOnDisk = FALSE;
> +    CapsuleFirstIndex = 1;
> +  }
> +  if (StrCmp(Argv[Argc - 1], L"-NR") == 0) {
> +    NoReset = TRUE;
> +    CapsuleLastIndex = Argc - 2;
> +  } else {
> +    NoReset = FALSE;
> +    CapsuleLastIndex = Argc - 1;
> +  }
> +  CapsuleNum = CapsuleLastIndex - CapsuleFirstIndex + 1;
> +
> +  if (CapsuleFirstIndex > CapsuleLastIndex) {
> +    Print(L"CapsuleApp: NO capsule image.\n");
> +    CleanArg();
> +    return EFI_UNSUPPORTED;
> +  }
> +  if (CapsuleNum > MAX_CAPSULE_NUM) {
> +    Print(L"CapsuleApp: Too many capsule images.\n");
> +    CleanArg();
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  ZeroMem(&CapsuleBuffer, sizeof(CapsuleBuffer));
> +  ZeroMem(&FileSize, sizeof(FileSize));
> +  BlockDescriptors = NULL;
> +
> +  for (Index = 0; Index < CapsuleNum; Index++) {
> +    CapsuleName = Argv[CapsuleFirstIndex + Index];
> +    Status = ReadFileToBuffer(CapsuleName, &FileSize[Index], &CapsuleBuffer[Index]);
> +    if (EFI_ERROR(Status)) {
> +      Print(L"CapsuleApp: capsule image (%s) is not found.\n", CapsuleName);
> +      goto Done;
> +    }
> +  }
> +
> +  if (NeedCopyOnDisk) {
> +    Status = CopyCapsuleToActiveEfiPartition(CapsuleBuffer, FileSize, CapsuleNum);
> +  } else {
> +    //
> +    // Every capsule use 2 descriptor 1 for data 1 for end
> +    //
> +    Status = BuildGatherList(CapsuleBuffer, FileSize, CapsuleNum, &BlockDescriptors);
> +  }
> +  if (EFI_ERROR(Status)) {
> +    goto Done;
> +  }
> +
> +  //
> +  // Call the runtime service capsule.
> +  //
> +  NeedReset = FALSE;
> +  for (Index = 0; Index < CapsuleNum; Index++) {
> +    CapsuleHeaderArray[Index] = (EFI_CAPSULE_HEADER *) CapsuleBuffer[Index];
> +    if ((CapsuleHeaderArray[Index]->Flags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET) != 0)
> {
> +      NeedReset = TRUE;
> +    }
> +  }
> +  CapsuleHeaderArray[CapsuleNum] = NULL;
> +  if (NoReset) {
> +    NeedReset = FALSE;
> +  }
> +
> +  //
> +  // Inquire platform capability of UpdateCapsule.
> +  //
> +  Status = gRT->QueryCapsuleCapabilities (CapsuleHeaderArray, CapsuleNum,
> &MaxCapsuleSize, &ResetType);
> +  if (EFI_ERROR(Status)) {
> +    Print (L"CapsuleApp: failed to query capsule capability - %r\n", Status);
> +    goto Done;
> +  }
> +
> +  for (Index = 0; Index < CapsuleNum; Index++) {
> +    if (FileSize[Index] > MaxCapsuleSize) {
> +      Print (L"CapsuleApp: capsule is too large to update, %ld is allowed\n",
> MaxCapsuleSize);
> +      Status = EFI_UNSUPPORTED;
> +      goto Done;
> +    }
> +  }
> +
> +  //
> +  // Check whether the input capsule image has the flag of persist across system
> reset.
> +  //
> +  if (NeedReset) {
> +    Status = gRT->UpdateCapsule(CapsuleHeaderArray,CapsuleNum,(UINTN)
> BlockDescriptors);
> +    if (Status != EFI_SUCCESS) {
> +      Print (L"CapsuleApp: failed to update capsule - %r\n", Status);
> +      goto Done;
> +    }
> +    //
> +    // For capsule who has reset flag, after calling UpdateCapsule service,triger a
> +    // system reset to process capsule persist across a system reset.
> +    //
> +    gRT->ResetSystem (ResetType, EFI_SUCCESS, 0, NULL);
> +  } else {
> +    //
> +    // For capsule who has no reset flag, only call UpdateCapsule Service without a
> +    // system reset. The service will process the capsule immediately.
> +    //
> +    Status = gRT->UpdateCapsule (CapsuleHeaderArray,CapsuleNum,(UINTN)
> BlockDescriptors);
> +    if (Status != EFI_SUCCESS) {
> +      Print (L"CapsuleApp: failed to update capsule - %r\n", Status);
> +    }
> +  }
> +
> +  Status = EFI_SUCCESS;
> +
> +Done:
> +  for (Index = 0; Index < CapsuleNum; Index++) {
> +    if (CapsuleBuffer[Index] != NULL) {
> +      FreePool (CapsuleBuffer[Index]);
> +    }
> +  }
> +
> +  CleanGatherList(BlockDescriptors, CapsuleNum);
> +  CleanArg();
> +
> +  return Status;
> +}
> diff --git a/MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf
> b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf
> new file mode 100644
> index 0000000..7ee44fc
> --- /dev/null
> +++ b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf
> @@ -0,0 +1,71 @@
> +##  @file
> +#  A shell application that triggers capsule update process.
> +#
> +# This application can trigger capsule update process. It can also
> +# generate capsule image, or dump capsule variable information.
> +#
> +#  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
> +#  This program and the accompanying materials
> +#  are licensed and made available under the terms and conditions of the BSD License
> +#  which accompanies this distribution.  The full text of the license may be found at
> +#  http://opensource.org/licenses/bsd-license.php
> +#
> +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +#
> +##
> +
> +[Defines]
> +  INF_VERSION                    = 0x00010006
> +  BASE_NAME                      = CapsuleApp
> +  MODULE_UNI_FILE                = CapsuleApp.uni
> +  FILE_GUID                      = 4CEF31DA-8682-4274-9CC4-AEE7516A5E7B
> +  MODULE_TYPE                    = UEFI_APPLICATION
> +  VERSION_STRING                 = 1.0
> +  ENTRY_POINT                    = UefiMain
> +
> +#
> +# The following information is for reference only and not required by the build tools.
> +#
> +#  VALID_ARCHITECTURES           = IA32 X64
> +#
> +
> +[Sources]
> +  CapsuleApp.c
> +  CapsuleDump.c
> +  AppSupport.c
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +
> +[Guids]
> +  gEfiFileInfoGuid
> +  gEfiPartTypeSystemPartGuid
> +  gEfiGlobalVariableGuid
> +  gEfiCapsuleReportGuid
> +  gEfiFmpCapsuleGuid
> +  gWindowsUxCapsuleGuid
> +  gEfiCertTypeRsa2048Sha256Guid
> +  gEfiCertPkcs7Guid
> +  gEfiSystemResourceTableGuid
> +
> +[Protocols]
> +  gEfiLoadedImageProtocolGuid
> +  gEfiSimpleFileSystemProtocolGuid
> +  gEfiGraphicsOutputProtocolGuid
> +  gEfiFirmwareManagementProtocolGuid
> +
> +[LibraryClasses]
> +  BaseLib
> +  UefiApplicationEntryPoint
> +  DebugLib
> +  MemoryAllocationLib
> +  UefiBootServicesTableLib
> +  UefiRuntimeServicesTableLib
> +  UefiLib
> +  PrintLib
> +  EdkiiSystemCapsuleLib
> +
> +[UserExtensions.TianoCore."ExtraFiles"]
> +  CapsuleAppExtra.uni
> diff --git a/MdeModulePkg/Application/CapsuleApp/CapsuleApp.uni
> b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.uni
> new file mode 100644
> index 0000000..54d6e12
> --- /dev/null
> +++ b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.uni
> @@ -0,0 +1,22 @@
> +// /** @file
> +// A shell application that triggers capsule update process.
> +//
> +// This application can trigger capsule update process. It can also
> +// generate capsule image, or dump capsule variable information.
> +//
> +// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
> +//
> +// This program and the accompanying materials
> +// are licensed and made available under the terms and conditions of the BSD License
> +// which accompanies this distribution. The full text of the license may be found at
> +// http://opensource.org/licenses/bsd-license.php
> +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +//
> +// **/
> +
> +
> +#string STR_MODULE_ABSTRACT             #language en-US "A shell application that
> triggers capsule update process."
> +
> +#string STR_MODULE_DESCRIPTION          #language en-US "This application can trigger
> capsule update process. It can also generate capsule image, or dump capsule variable
> information."
> +
> diff --git a/MdeModulePkg/Application/CapsuleApp/CapsuleAppExtra.uni
> b/MdeModulePkg/Application/CapsuleApp/CapsuleAppExtra.uni
> new file mode 100644
> index 0000000..b5a8840
> --- /dev/null
> +++ b/MdeModulePkg/Application/CapsuleApp/CapsuleAppExtra.uni
> @@ -0,0 +1,19 @@
> +// /** @file
> +// CapsuleApp Localized Strings and Content
> +//
> +// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
> +//
> +// This program and the accompanying materials
> +// are licensed and made available under the terms and conditions of the BSD License
> +// which accompanies this distribution. The full text of the license may be found at
> +// http://opensource.org/licenses/bsd-license.php
> +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +//
> +// **/
> +
> +#string STR_PROPERTIES_MODULE_NAME
> +#language en-US
> +"Capsule Application"
> +
> +
> diff --git a/MdeModulePkg/Application/CapsuleApp/CapsuleDump.c
> b/MdeModulePkg/Application/CapsuleApp/CapsuleDump.c
> new file mode 100644
> index 0000000..c56f41f
> --- /dev/null
> +++ b/MdeModulePkg/Application/CapsuleApp/CapsuleDump.c
> @@ -0,0 +1,840 @@
> +/** @file
> +  Dump Capsule image information.
> +
> +  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the BSD License
> +  which accompanies this distribution.  The full text of the license may be found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +
> +**/
> +
> +#include <PiDxe.h>
> +#include <Library/BaseLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/UefiRuntimeServicesTableLib.h>
> +#include <Library/UefiLib.h>
> +#include <Library/PrintLib.h>
> +#include <Library/EdkiiSystemCapsuleLib.h>
> +#include <Protocol/FirmwareManagement.h>
> +#include <Guid/ImageAuthentication.h>
> +#include <Guid/EdkiiSystemFmpCapsule.h>
> +#include <Guid/CapsuleReport.h>
> +#include <Guid/SystemResourceTable.h>
> +#include <Guid/FmpCapsule.h>
> +#include <IndustryStandard/WindowsUxCapsule.h>
> +
> +/**
> +  Read a file.
> +
> +  @param FileName        The file to be read.
> +  @param BufferSize      The file buffer size
> +  @param Buffer          The file buffer
> +
> +  @retval EFI_SUCCESS    Read file successfully
> +  @retval EFI_NOT_FOUND  File not found
> +**/
> +EFI_STATUS
> +ReadFileToBuffer(
> +  IN  CHAR16                               *FileName,
> +  OUT UINTN                                *BufferSize,
> +  OUT VOID                                 **Buffer
> +  );
> +
> +extern UINTN  Argc;
> +extern CHAR16 *Argv[];
> +
> +/**
> +  Dump UX capsule information.
> +
> +  @param CapsuleHeader      The UX capsule header
> +**/
> +VOID
> +DumpUxCapsule(
> +  IN EFI_CAPSULE_HEADER  *CapsuleHeader
> +  )
> +{
> +  EFI_DISPLAY_CAPSULE                           *DisplayCapsule;
> +  DisplayCapsule = (EFI_DISPLAY_CAPSULE *)CapsuleHeader;
> +  Print(L"[UxCapusule]\n");
> +  Print(L"CapsuleHeader:\n");
> +  Print(L"  CapsuleGuid      - %g\n", &DisplayCapsule->CapsuleHeader.CapsuleGuid);
> +  Print(L"  HeaderSize       - 0x%x\n", DisplayCapsule->CapsuleHeader.HeaderSize);
> +  Print(L"  Flags            - 0x%x\n", DisplayCapsule->CapsuleHeader.Flags);
> +  Print(L"  CapsuleImageSize - 0x%x\n", DisplayCapsule-
> >CapsuleHeader.CapsuleImageSize);
> +  Print(L"ImagePayload:\n");
> +  Print(L"  Version          - 0x%x\n", DisplayCapsule->ImagePayload.Version);
> +  Print(L"  Checksum         - 0x%x\n", DisplayCapsule->ImagePayload.Checksum);
> +  Print(L"  ImageType        - 0x%x\n", DisplayCapsule->ImagePayload.ImageType);
> +  Print(L"  Mode             - 0x%x\n", DisplayCapsule->ImagePayload.Mode);
> +  Print(L"  OffsetX          - 0x%x\n", DisplayCapsule->ImagePayload.OffsetX);
> +  Print(L"  OffsetY          - 0x%x\n", DisplayCapsule->ImagePayload.OffsetY);
> +}
> +
> +/**
> +  Dump FMP image authentication information.
> +
> +  @param Image      The FMP capsule image
> +  @param ImageSize  The size of the FMP capsule image in bytes.
> +
> +  @return the size of FMP authentication.
> +**/
> +UINTN
> +DumpImageAuthentication(
> +  IN VOID   *Image,
> +  IN UINTN  ImageSize
> +  )
> +{
> +  EFI_FIRMWARE_IMAGE_AUTHENTICATION             *ImageAuthentication;
> +
> +  ImageAuthentication = Image;
> +  if (CompareGuid(&ImageAuthentication->AuthInfo.CertType, &gEfiCertPkcs7Guid) ||
> +      CompareGuid(&ImageAuthentication->AuthInfo.CertType,
> &gEfiCertTypeRsa2048Sha256Guid)) {
> +    Print(L"[ImageAuthentication]\n");
> +    Print(L"  MonotonicCount   - 0x%lx\n", ImageAuthentication->MonotonicCount);
> +    Print(L"WIN_CERTIFICATE:\n");
> +    Print(L"  dwLength         - 0x%x\n", ImageAuthentication->AuthInfo.Hdr.dwLength);
> +    Print(L"  wRevision        - 0x%x\n", ImageAuthentication-
> >AuthInfo.Hdr.wRevision);
> +    Print(L"  wCertificateType - 0x%x\n", ImageAuthentication-
> >AuthInfo.Hdr.wCertificateType);
> +    Print(L"  CertType         - %g\n", &ImageAuthentication->AuthInfo.CertType);
> +    return sizeof(ImageAuthentication->MonotonicCount) + ImageAuthentication-
> >AuthInfo.Hdr.dwLength;
> +  } else {
> +    return 0;
> +  }
> +}
> +
> +/**
> +  Dump EDKII system FMP capsule.
> +
> +  @param Image      The EDKII system FMP capsule.
> +  @param ImageSize  The size of the EDKII system FMP capsule in bytes.
> +**/
> +VOID
> +DumpEdkiiSystemFmpCapsule(
> +  IN VOID   *Image,
> +  IN UINTN  ImageSize
> +  )
> +{
> +  UINTN                                         ImageOffset;
> +  VOID                                          *BiosImage;
> +  UINTN                                         BiosImageSize;
> +  BOOLEAN                                       Result;
> +  EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR        *TempImageFmpInfo;
> +  EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR        *ImageFmpInfo;
> +  UINTN                                         ImageFmpInfoSize;
> +
> +  //
> +  // We do not know if there is EFI_FIRMWARE_IMAGE_AUTHENTICATION.
> +  // so just *try* to parse it
> +  //
> +  ImageOffset = DumpImageAuthentication(Image, ImageSize);
> +  Image = (UINT8 *)Image + ImageOffset;
> +  ImageSize -= ImageOffset;
> +  Print(L"[Image]\n");
> +  Print(L"  ImageSize   - 0x%x\n", ImageSize);
> +
> +  Result = ExtractConfigImage(Image, ImageSize, &BiosImage, &BiosImageSize);
> +  if (Result) {
> +    Print(L"  ConfigFileSize  - 0x%x\n", BiosImageSize);
> +  }
> +  Result = ExtractDriverFvImage(Image, ImageSize, &BiosImage, &BiosImageSize);
> +  if (Result) {
> +    Print(L"  DriverFvSize    - 0x%x\n", BiosImageSize);
> +  }
> +  Result = ExtractSystemFirmwareImage(Image, ImageSize, &BiosImage, &BiosImageSize);
> +  if (Result) {
> +    Print(L"  BiosImageSize   - 0x%x\n", BiosImageSize);
> +  }
> +  Result = ExtractSystemFirmwareImageFmpInfo(BiosImage, BiosImageSize,
> &TempImageFmpInfo, &ImageFmpInfoSize);
> +  if (Result) {
> +    ImageFmpInfo = AllocateCopyPool(ImageFmpInfoSize, TempImageFmpInfo);
> +    if (ImageFmpInfo != NULL) {
> +      Print(L"[ImageFmpInfo]\n");
> +      Print(L"  Signature                      - 0x%x\n", ImageFmpInfo->Signature);
> +      Print(L"  HeaderLength                   - 0x%x\n", ImageFmpInfo->HeaderLength);
> +      Print(L"  Length                         - 0x%x\n", ImageFmpInfo->Length);
> +      Print(L"  PackageVersion                 - 0x%x\n", ImageFmpInfo-
> >PackageVersion);
> +      Print(L"  PackageVersionNameStringOffset - 0x%x\n", ImageFmpInfo-
> >PackageVersionNameStringOffset);
> +      if (ImageFmpInfo->PackageVersionNameStringOffset != 0) {
> +        Print(L"                                 - %s\n", (UINT8 *)ImageFmpInfo +
> ImageFmpInfo->PackageVersionNameStringOffset);
> +      }
> +      Print(L"  ImageIndex                     - 0x%x\n", ImageFmpInfo->ImageIndex);
> +      Print(L"  ImageTypeId                    - %g\n", &ImageFmpInfo->ImageTypeId);
> +      Print(L"  ImageId                        - 0x%lx\n", ImageFmpInfo->ImageId);
> +      Print(L"  ImageIdNameStringOffset        - 0x%x\n", ImageFmpInfo-
> >ImageIdNameStringOffset);
> +      if (ImageFmpInfo->ImageIdNameStringOffset != 0) {
> +        Print(L"                                 - %s\n", (UINT8 *)ImageFmpInfo +
> ImageFmpInfo->ImageIdNameStringOffset);
> +      }
> +      Print(L"  Version                        - 0x%x\n", ImageFmpInfo->Version);
> +      Print(L"  VersionNameStringOffset        - 0x%x\n", ImageFmpInfo-
> >VersionNameStringOffset);
> +      if (ImageFmpInfo->VersionNameStringOffset != 0) {
> +        Print(L"                                 - %s\n", (UINT8 *)ImageFmpInfo +
> ImageFmpInfo->VersionNameStringOffset);
> +      }
> +      Print(L"  Size                           - 0x%lx\n", ImageFmpInfo->Size);
> +      Print(L"  AttributesSupported            - 0x%lx\n", ImageFmpInfo-
> >AttributesSupported);
> +      Print(L"  AttributesSetting              - 0x%lx\n", ImageFmpInfo-
> >AttributesSetting);
> +      Print(L"  Compatibilities                - 0x%lx\n", ImageFmpInfo-
> >Compatibilities);
> +      Print(L"  LowestSupportedImageVersion    - 0x%x\n", ImageFmpInfo-
> >LowestSupportedImageVersion);
> +      Print(L"  LastAttemptVersion             - 0x%x\n", ImageFmpInfo-
> >LastAttemptVersion);
> +      Print(L"  LastAttemptStatus              - 0x%x\n", ImageFmpInfo-
> >LastAttemptStatus);
> +      Print(L"  HardwareInstance               - 0x%lx\n", ImageFmpInfo-
> >HardwareInstance);
> +      Print(L"  Version                        - 0x%x\n", ImageFmpInfo->Version);
> +      FreePool(ImageFmpInfo);
> +    }
> +  }
> +}
> +
> +/**
> +  Dump a non-nested FMP capsule.
> +
> +  @param  CapsuleHeader  A pointer to CapsuleHeader
> +  @param  IsSystemFmp    If it is a system FMP
> +**/
> +VOID
> +DumpFmpCapsule(
> +  IN EFI_CAPSULE_HEADER  *CapsuleHeader,
> +  IN BOOLEAN             IsSystemFmp
> +  )
> +{
> +  EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER        *FmpCapsuleHeader;
> +  UINT64                                        *ItemOffsetList;
> +  UINTN                                         Index;
> +  UINTN                                         Count;
> +  EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER  *FmpImageHeader;
> +  VOID                                          *Image;
> +
> +  Print(L"[FmpCapusule]\n");
> +  Print(L"CapsuleHeader:\n");
> +  Print(L"  CapsuleGuid      - %g\n", &CapsuleHeader->CapsuleGuid);
> +  Print(L"  HeaderSize       - 0x%x\n", CapsuleHeader->HeaderSize);
> +  Print(L"  Flags            - 0x%x\n", CapsuleHeader->Flags);
> +  Print(L"  CapsuleImageSize - 0x%x\n", CapsuleHeader->CapsuleImageSize);
> +
> +  FmpCapsuleHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *)((UINT8 *)CapsuleHeader
> + CapsuleHeader->HeaderSize);
> +  ItemOffsetList = (UINT64 *)(FmpCapsuleHeader + 1);
> +  Print(L"FmpHeader:\n");
> +  Print(L"  Version             - 0x%x\n", FmpCapsuleHeader->Version);
> +  Print(L"  EmbeddedDriverCount - 0x%x\n", FmpCapsuleHeader->EmbeddedDriverCount);
> +  Print(L"  PayloadItemCount    - 0x%x\n", FmpCapsuleHeader->PayloadItemCount);
> +  Count = FmpCapsuleHeader->EmbeddedDriverCount + FmpCapsuleHeader->PayloadItemCount;
> +  for (Index = 0; Index < Count; Index++) {
> +    Print(L"  Offset[%d]           - 0x%x\n", Index, ItemOffsetList[Index]);
> +  }
> +
> +  for (Index = FmpCapsuleHeader->EmbeddedDriverCount; Index < Count; Index++) {
> +    Print(L"FmpPayload[%d] ImageHeader:\n", Index);
> +    FmpImageHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *)((UINT8
> *)FmpCapsuleHeader + ItemOffsetList[Index]);
> +    Print(L"  Version                - 0x%x\n", FmpImageHeader->Version);
> +    Print(L"  UpdateImageTypeId      - %g\n", &FmpImageHeader->UpdateImageTypeId);
> +    Print(L"  UpdateImageIndex       - 0x%x\n", FmpImageHeader->UpdateImageIndex);
> +    Print(L"  UpdateImageSize        - 0x%x\n", FmpImageHeader->UpdateImageSize);
> +    Print(L"  UpdateVendorCodeSize   - 0x%x\n", FmpImageHeader->UpdateVendorCodeSize);
> +    if (FmpImageHeader->Version >=
> EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {
> +      Print(L"  UpdateHardwareInstance - 0x%lx\n", FmpImageHeader-
> >UpdateHardwareInstance);
> +    }
> +    if (FmpImageHeader->Version >=
> EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {
> +      Image = (UINT8 *)(FmpImageHeader + 1);
> +    }  else {
> +      Image = (UINT8 *)FmpImageHeader +
> OFFSET_OF(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER, UpdateHardwareInstance);
> +    }
> +    if (IsSystemFmp) {
> +      DumpEdkiiSystemFmpCapsule(Image, FmpImageHeader->UpdateImageSize);
> +    }
> +  }
> +}
> +
> +/**
> +  Return if there is a FMP header below capsule header.
> +
> +  @param[in] CapsuleHeader A pointer to EFI_CAPSULE_HEADER
> +
> +  @retval TRUE  There is a FMP header below capsule header.
> +  @retval FALSE There is not a FMP header below capsule header
> +**/
> +BOOLEAN
> +IsNestedFmpCapsule(
> +  IN EFI_CAPSULE_HEADER         *CapsuleHeader
> +  )
> +{
> +  EFI_STATUS                 Status;
> +  EFI_SYSTEM_RESOURCE_TABLE  *Esrt;
> +  EFI_SYSTEM_RESOURCE_ENTRY  *EsrtEntry;
> +  UINTN                      Index;
> +  BOOLEAN                    EsrtGuidFound;
> +  EFI_CAPSULE_HEADER         *NestedCapsuleHeader;
> +  UINTN                      NestedCapsuleSize;
> +
> +  //
> +  // Check ESRT
> +  //
> +  EsrtGuidFound = FALSE;
> +  Status = EfiGetSystemConfigurationTable(&gEfiSystemResourceTableGuid, (VOID
> **)&Esrt);
> +  if (!EFI_ERROR(Status)) {
> +    EsrtEntry = (VOID *)(Esrt + 1);
> +    for (Index = 0; Index < Esrt->FwResourceCount; Index++, EsrtEntry++) {
> +      if (CompareGuid(&EsrtEntry->FwClass, &CapsuleHeader->CapsuleGuid)) {
> +        EsrtGuidFound = TRUE;
> +        break;
> +      }
> +    }
> +  }
> +
> +  if (!EsrtGuidFound) {
> +    return FALSE;
> +  }
> +
> +  //
> +  // Check nested capsule header
> +  // FMP GUID after ESRT one
> +  //
> +  NestedCapsuleHeader = (EFI_CAPSULE_HEADER *)((UINT8 *)CapsuleHeader + CapsuleHeader-
> >HeaderSize);
> +  NestedCapsuleSize = (UINTN)CapsuleHeader + CapsuleHeader->HeaderSize -
> (UINTN)NestedCapsuleHeader;
> +  if (NestedCapsuleSize < sizeof(EFI_CAPSULE_HEADER)) {
> +    return FALSE;
> +  }
> +  if (!CompareGuid(&NestedCapsuleHeader->CapsuleGuid, &gEfiFmpCapsuleGuid)) {
> +    return FALSE;
> +  }
> +  return TRUE;
> +}
> +
> +/**
> +  Dump capsule information
> +
> +  @retval EFI_SUCCESS            The capsule information is dumped.
> +  @retval EFI_UNSUPPORTED        Input parameter is not valid.
> +**/
> +EFI_STATUS
> +DumpCapsule(
> +  VOID
> +  )
> +{
> +  CHAR16                                        *CapsuleName;
> +  VOID                                          *Buffer;
> +  UINTN                                         FileSize;
> +  BOOLEAN                                       IsSystemFmp;
> +  EFI_CAPSULE_HEADER                            *CapsuleHeader;
> +  EFI_STATUS                                    Status;
> +
> +  if (Argc != 3) {
> +    Print(L"CapsuleApp: Invalid Parameter.\n");
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  IsSystemFmp = FALSE;
> +  if (StrCmp(Argv[1], L"-DS") == 0) {
> +    IsSystemFmp = TRUE;
> +  }
> +
> +  CapsuleName = Argv[2];
> +  Status = ReadFileToBuffer(CapsuleName, &FileSize, &Buffer);
> +  if (EFI_ERROR(Status)) {
> +    Print(L"CapsuleApp: Capsule (%s) is not found.\n", CapsuleName);
> +    goto Done;
> +  }
> +
> +  CapsuleHeader = Buffer;
> +  if (CompareGuid(&CapsuleHeader->CapsuleGuid, &gWindowsUxCapsuleGuid)) {
> +    DumpUxCapsule(CapsuleHeader);
> +    Status = EFI_SUCCESS;
> +    goto Done;
> +  }
> +
> +  if (CompareGuid(&CapsuleHeader->CapsuleGuid, &gEfiFmpCapsuleGuid)) {
> +    DumpFmpCapsule(CapsuleHeader, IsSystemFmp);
> +  }
> +  if (IsNestedFmpCapsule(CapsuleHeader)) {
> +    Print(L"[NestedCapusule]\n");
> +    Print(L"CapsuleHeader:\n");
> +    Print(L"  CapsuleGuid      - %g\n", &CapsuleHeader->CapsuleGuid);
> +    Print(L"  HeaderSize       - 0x%x\n", CapsuleHeader->HeaderSize);
> +    Print(L"  Flags            - 0x%x\n", CapsuleHeader->Flags);
> +    Print(L"  CapsuleImageSize - 0x%x\n", CapsuleHeader->CapsuleImageSize);
> +    DumpFmpCapsule((EFI_CAPSULE_HEADER *)((UINTN)CapsuleHeader + CapsuleHeader-
> >HeaderSize), IsSystemFmp);
> +  }
> +
> +Done:
> +  FreePool(Buffer);
> +  return Status;
> +}
> +
> +/**
> +  Dump capsule status variable.
> +
> +  @retval EFI_SUCCESS            The capsule status variable is dumped.
> +  @retval EFI_UNSUPPORTED        Input parameter is not valid.
> +**/
> +EFI_STATUS
> +DmpCapsuleStatusVariable(
> +  VOID
> +  )
> +{
> +  EFI_STATUS                          Status;
> +  UINT32                              Index;
> +  CHAR16                              CapsuleVarName[20];
> +  CHAR16                              *TempVarName;
> +  EFI_CAPSULE_RESULT_VARIABLE_HEADER  *CapsuleResult;
> +  EFI_CAPSULE_RESULT_VARIABLE_FMP     *CapsuleResultFmp;
> +  UINTN                               CapsuleFileNameSize;
> +  CHAR16                              CapsuleIndexData[12];
> +  CHAR16                              *CapsuleIndex;
> +
> +  Status = GetVariable2(
> +             L"CapsuleMax",
> +             &gEfiCapsuleReportGuid,
> +             (VOID **)&CapsuleIndex,
> +             NULL
> +             );
> +  if (!EFI_ERROR(Status)) {
> +    CopyMem(CapsuleIndexData, CapsuleIndex, 11 * sizeof(CHAR16));
> +    CapsuleIndexData[11] = 0;
> +    Print(L"CapsuleMax - %s\n", CapsuleIndexData);
> +    FreePool(CapsuleIndex);
> +  }
> +  Status = GetVariable2(
> +             L"CapsuleLast",
> +             &gEfiCapsuleReportGuid,
> +             (VOID **)&CapsuleIndex,
> +             NULL
> +             );
> +  if (!EFI_ERROR(Status)) {
> +    CopyMem(CapsuleIndexData, CapsuleIndex, 11 * sizeof(CHAR16));
> +    CapsuleIndexData[11] = 0;
> +    Print(L"CapsuleLast - %s\n", CapsuleIndexData);
> +    FreePool(CapsuleIndex);
> +  }
> +
> +
> +  StrCpyS (CapsuleVarName, sizeof(CapsuleVarName)/sizeof(CapsuleVarName[0]),
> L"Capsule");
> +  TempVarName = CapsuleVarName + StrLen (CapsuleVarName);
> +  Index = 0;
> +
> +  while (TRUE) {
> +    UnicodeSPrint (TempVarName, 5 * sizeof(CHAR16), L"%04x", Index);
> +
> +    Status = GetVariable2 (
> +               CapsuleVarName,
> +               &gEfiCapsuleReportGuid,
> +               (VOID **) &CapsuleResult,
> +               NULL
> +               );
> +    if (Status == EFI_NOT_FOUND) {
> +      break;
> +    } else if (EFI_ERROR(Status)) {
> +      continue;
> +    }
> +
> +    //
> +    // display capsule process status
> +    //
> +    if (CapsuleResult->VariableTotalSize >=
> sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER)) {
> +      Print (L"CapsuleName: %s\n", CapsuleVarName);
> +      Print (L"  Capsule Guid: %g\n", &CapsuleResult->CapsuleGuid);
> +      Print (L"  Capsule ProcessedTime: %t\n", &CapsuleResult->CapsuleProcessed);
> +      Print (L"  Capsule Status: %r\n", CapsuleResult->CapsuleStatus);
> +    }
> +
> +    if (CompareGuid(&CapsuleResult->CapsuleGuid, &gEfiFmpCapsuleGuid)) {
> +      if (CapsuleResult->VariableTotalSize >=
> sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER) + sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP)) {
> +        CapsuleResultFmp = (EFI_CAPSULE_RESULT_VARIABLE_FMP *)(CapsuleResult + 1);
> +        Print(L"  Capsule FMP Version: 0x%x\n", CapsuleResultFmp->Version);
> +        Print(L"  Capsule FMP PayloadIndex: 0x%x\n", CapsuleResultFmp->PayloadIndex);
> +        Print(L"  Capsule FMP UpdateImageIndex: 0x%x\n", CapsuleResultFmp-
> >UpdateImageIndex);
> +        Print(L"  Capsule FMP UpdateImageTypeId: %g\n", &CapsuleResultFmp-
> >UpdateImageTypeId);
> +        if (CapsuleResult->VariableTotalSize >
> sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER) + sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP)) {
> +          Print(L"  Capsule FMP CapsuleFileName: %s\n", (CapsuleResultFmp + 1));
> +          CapsuleFileNameSize = StrSize((CHAR16 *)(CapsuleResultFmp + 1));
> +          if (CapsuleResult->VariableTotalSize >
> sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER) + sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP) +
> CapsuleFileNameSize) {
> +            Print(L"  Capsule FMP CapsuleTarget: %s\n", (UINT8 *)(CapsuleResultFmp +
> 1) + CapsuleFileNameSize);
> +          }
> +        }
> +      }
> +    }
> +
> +    FreePool(CapsuleResult);
> +
> +    Index++;
> +    if (Index > 0xFFFF) {
> +      break;
> +    }
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +CHAR8 *mFwTypeString[] = {
> +  "Unknown",
> +  "SystemFirmware",
> +  "DeviceFirmware",
> +  "UefiDriver",
> +};
> +
> +CHAR8 *mLastAttemptStatusString[] = {
> +  "Success",
> +  "Error: Unsuccessful",
> +  "Error: Insufficient Resources",
> +  "Error: Incorrect Version",
> +  "Error: Invalid Format",
> +  "Error: Auth Error",
> +  "Error: Power Event AC",
> +  "Error: Power Event Battery",
> +};
> +
> +/**
> +  Convert FwType to a string.
> +
> +  @param FwType  FwType in ESRT
> +
> +  @return a string for FwType.
> +**/
> +CHAR8 *
> +FwTypeToString(
> +  IN UINT32 FwType
> +  )
> +{
> +  if (FwType < sizeof(mFwTypeString) / sizeof(mFwTypeString[0])) {
> +    return mFwTypeString[FwType];
> +  } else {
> +    return "Invalid";
> +  }
> +}
> +
> +/**
> +  Convert LastAttemptStatus to a string.
> +
> +  @param LastAttemptStatus  LastAttemptStatus in FMP or ESRT
> +
> +  @return a string for LastAttemptStatus.
> +**/
> +CHAR8 *
> +LastAttemptStatusToString(
> +  IN UINT32 LastAttemptStatus
> +  )
> +{
> +  if (LastAttemptStatus < sizeof(mLastAttemptStatusString) /
> sizeof(mLastAttemptStatusString[0])) {
> +    return mLastAttemptStatusString[LastAttemptStatus];
> +  } else {
> +    return "Error: Unknown";
> +  }
> +}
> +
> +/**
> +  Dump ESRT entry.
> +
> +  @param EsrtEntry  ESRT entry
> +**/
> +VOID
> +DumpEsrtEntry(
> +  IN EFI_SYSTEM_RESOURCE_ENTRY  *EsrtEntry
> +  )
> +{
> +  Print(L"  FwClass                  - %g\n", &EsrtEntry->FwClass);
> +  Print(L"  FwType                   - 0x%x (%a)\n", EsrtEntry->FwType,
> FwTypeToString(EsrtEntry->FwType));
> +  Print(L"  FwVersion                - 0x%x\n", EsrtEntry->FwVersion);
> +  Print(L"  LowestSupportedFwVersion - 0x%x\n", EsrtEntry->LowestSupportedFwVersion);
> +  Print(L"  CapsuleFlags             - 0x%x\n", EsrtEntry->CapsuleFlags);
> +  Print(L"    PERSIST_ACROSS_RESET   - 0x%x\n", EsrtEntry->CapsuleFlags &
> CAPSULE_FLAGS_PERSIST_ACROSS_RESET);
> +  Print(L"    POPULATE_SYSTEM_TABLE  - 0x%x\n", EsrtEntry->CapsuleFlags &
> CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE);
> +  Print(L"    INITIATE_RESET         - 0x%x\n", EsrtEntry->CapsuleFlags &
> CAPSULE_FLAGS_INITIATE_RESET);
> +  Print(L"  LastAttemptVersion       - 0x%x\n", EsrtEntry->LastAttemptVersion);
> +  Print(L"  LastAttemptStatus        - 0x%x (%a)\n", EsrtEntry->LastAttemptStatus,
> LastAttemptStatusToString(EsrtEntry->LastAttemptStatus));
> +}
> +
> +/**
> +  Dump ESRT table.
> +
> +  @param Esrt  ESRT table
> +**/
> +VOID
> +DumpEsrt(
> +  IN EFI_SYSTEM_RESOURCE_TABLE  *Esrt
> +  )
> +{
> +  UINTN                      Index;
> +  EFI_SYSTEM_RESOURCE_ENTRY  *EsrtEntry;
> +
> +  Print(L"EFI_SYSTEM_RESOURCE_TABLE:\n");
> +  Print(L"FwResourceCount    - 0x%x\n", Esrt->FwResourceCount);
> +  Print(L"FwResourceCountMax - 0x%x\n", Esrt->FwResourceCountMax);
> +  Print(L"FwResourceVersion  - 0x%lx\n", Esrt->FwResourceVersion);
> +
> +  EsrtEntry = (VOID *)(Esrt + 1);
> +  for (Index = 0; Index < Esrt->FwResourceCount; Index++) {
> +    Print(L"EFI_SYSTEM_RESOURCE_ENTRY (%d):\n", Index);
> +    DumpEsrtEntry(EsrtEntry);
> +    EsrtEntry++;
> +  }
> +}
> +
> +/**
> +  Dump ESRT info.
> +**/
> +VOID
> +DumpEsrtData (
> +  VOID
> +  )
> +{
> +  EFI_STATUS                 Status;
> +  EFI_SYSTEM_RESOURCE_TABLE  *Esrt;
> +
> +  Print(L"##############\n");
> +  Print(L"# ESRT TABLE #\n");
> +  Print(L"##############\n");
> +
> +  Status = EfiGetSystemConfigurationTable (&gEfiSystemResourceTableGuid, (VOID
> **)&Esrt);
> +  if (EFI_ERROR(Status)) {
> +    Print(L"ESRT - %r\n", Status);
> +    return;
> +  }
> +  DumpEsrt(Esrt);
> +  Print(L"\n");
> +}
> +
> +/**
> +  Dump FMP information.
> +
> +  @param ImageInfoSize       The size of ImageInfo, in bytes.
> +  @param ImageInfo           A pointer to EFI_FIRMWARE_IMAGE_DESCRIPTOR.
> +  @param DescriptorVersion   The version of EFI_FIRMWARE_IMAGE_DESCRIPTOR.
> +  @param DescriptorCount     The count of EFI_FIRMWARE_IMAGE_DESCRIPTOR.
> +  @param DescriptorSize      The size of an individual EFI_FIRMWARE_IMAGE_DESCRIPTOR,
> in bytes.
> +  @param PackageVersion      The version of package.
> +  @param PackageVersionName  The version name of package.
> +**/
> +VOID
> +DumpFmpImageInfo(
> +  IN UINTN                           ImageInfoSize,
> +  IN EFI_FIRMWARE_IMAGE_DESCRIPTOR   *ImageInfo,
> +  IN UINT32                          DescriptorVersion,
> +  IN UINT8                           DescriptorCount,
> +  IN UINTN                           DescriptorSize,
> +  IN UINT32                          PackageVersion,
> +  IN CHAR16                          *PackageVersionName
> +  )
> +{
> +  EFI_FIRMWARE_IMAGE_DESCRIPTOR                 *CurrentImageInfo;
> +  UINTN                                         Index;
> +
> +  Print(L"  DescriptorVersion  - 0x%x\n", DescriptorVersion);
> +  Print(L"  DescriptorCount    - 0x%x\n", DescriptorCount);
> +  Print(L"  DescriptorSize     - 0x%x\n", DescriptorSize);
> +  Print(L"  PackageVersion     - 0x%x\n", PackageVersion);
> +  Print(L"  PackageVersionName - \"%s\"\n", PackageVersionName);
> +  CurrentImageInfo = ImageInfo;
> +  for (Index = 0; Index < DescriptorCount; Index++) {
> +    Print(L"  ImageDescriptor (%d)\n", Index);
> +    Print(L"    ImageIndex                  - 0x%x\n", CurrentImageInfo->ImageIndex);
> +    Print(L"    ImageTypeId                 - %g\n", &CurrentImageInfo->ImageTypeId);
> +    Print(L"    ImageId                     - 0x%lx\n", CurrentImageInfo->ImageId);
> +    Print(L"    ImageIdName                 - \"%s\"\n", CurrentImageInfo-
> >ImageIdName);
> +    Print(L"    Version                     - 0x%x\n", CurrentImageInfo->Version);
> +    Print(L"    VersionName                 - \"%s\"\n", CurrentImageInfo-
> >VersionName);
> +    Print(L"    Size                        - 0x%x\n", CurrentImageInfo->Size);
> +    Print(L"    AttributesSupported         - 0x%lx\n", CurrentImageInfo-
> >AttributesSupported);
> +    Print(L"      IMAGE_UPDATABLE           - 0x%lx\n", CurrentImageInfo-
> >AttributesSupported & IMAGE_ATTRIBUTE_IMAGE_UPDATABLE);
> +    Print(L"      RESET_REQUIRED            - 0x%lx\n", CurrentImageInfo-
> >AttributesSupported & IMAGE_ATTRIBUTE_RESET_REQUIRED);
> +    Print(L"      AUTHENTICATION_REQUIRED   - 0x%lx\n", CurrentImageInfo-
> >AttributesSupported & IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);
> +    Print(L"      IN_USE                    - 0x%lx\n", CurrentImageInfo-
> >AttributesSupported & IMAGE_ATTRIBUTE_IN_USE);
> +    Print(L"      UEFI_IMAGE                - 0x%lx\n", CurrentImageInfo-
> >AttributesSupported & IMAGE_ATTRIBUTE_UEFI_IMAGE);
> +    Print(L"    AttributesSetting           - 0x%lx\n", CurrentImageInfo-
> >AttributesSetting);
> +    Print(L"      IMAGE_UPDATABLE           - 0x%lx\n", CurrentImageInfo-
> >AttributesSetting & IMAGE_ATTRIBUTE_IMAGE_UPDATABLE);
> +    Print(L"      RESET_REQUIRED            - 0x%lx\n", CurrentImageInfo-
> >AttributesSetting & IMAGE_ATTRIBUTE_RESET_REQUIRED);
> +    Print(L"      AUTHENTICATION_REQUIRED   - 0x%lx\n", CurrentImageInfo-
> >AttributesSetting & IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);
> +    Print(L"      IN_USE                    - 0x%lx\n", CurrentImageInfo-
> >AttributesSetting & IMAGE_ATTRIBUTE_IN_USE);
> +    Print(L"      UEFI_IMAGE                - 0x%lx\n", CurrentImageInfo-
> >AttributesSetting & IMAGE_ATTRIBUTE_UEFI_IMAGE);
> +    Print(L"    Compatibilities             - 0x%lx\n", CurrentImageInfo-
> >Compatibilities);
> +    Print(L"      COMPATIB_CHECK_SUPPORTED  - 0x%lx\n", CurrentImageInfo-
> >Compatibilities & IMAGE_COMPATIBILITY_CHECK_SUPPORTED);
> +    if (DescriptorVersion > 1) {
> +      Print(L"    LowestSupportedImageVersion - 0x%x\n", CurrentImageInfo-
> >LowestSupportedImageVersion);
> +      if (DescriptorVersion > 2) {
> +        Print(L"    LastAttemptVersion          - 0x%x\n", CurrentImageInfo-
> >LastAttemptVersion);
> +        Print(L"    LastAttemptStatus           - 0x%x (%a)\n", CurrentImageInfo-
> >LastAttemptStatus, LastAttemptStatusToString(CurrentImageInfo->LastAttemptStatus));
> +        Print(L"    HardwareInstance            - 0x%lx\n", CurrentImageInfo-
> >HardwareInstance);
> +      }
> +    }
> +    //
> +    // Use DescriptorSize to move ImageInfo Pointer to stay compatible with different
> ImageInfo version
> +    //
> +    CurrentImageInfo = (EFI_FIRMWARE_IMAGE_DESCRIPTOR *)((UINT8 *)CurrentImageInfo +
> DescriptorSize);
> +  }
> +}
> +
> +/**
> +  Dump FMP package information.
> +
> +  @param PackageVersion             The version of package.
> +  @param PackageVersionName         The version name of package.
> +  @param PackageVersionNameMaxLen   The maximum length of PackageVersionName.
> +  @param AttributesSupported        Package attributes that are supported by this
> device.
> +  @param AttributesSetting          Package attributes.
> +**/
> +VOID
> +DumpFmpPackageInfo(
> +  IN UINT32                           PackageVersion,
> +  IN CHAR16                           *PackageVersionName,
> +  IN UINT32                           PackageVersionNameMaxLen,
> +  IN UINT64                           AttributesSupported,
> +  IN UINT64                           AttributesSetting
> +  )
> +{
> +  Print(L"  PackageVersion              - 0x%x\n", PackageVersion);
> +  Print(L"  PackageVersionName          - \"%s\"\n", PackageVersionName);
> +  Print(L"  PackageVersionNameMaxLen    - 0x%x\n", PackageVersionNameMaxLen);
> +  Print(L"  AttributesSupported         - 0x%lx\n", AttributesSupported);
> +  Print(L"    IMAGE_UPDATABLE           - 0x%lx\n", AttributesSupported &
> IMAGE_ATTRIBUTE_IMAGE_UPDATABLE);
> +  Print(L"    RESET_REQUIRED            - 0x%lx\n", AttributesSupported &
> IMAGE_ATTRIBUTE_RESET_REQUIRED);
> +  Print(L"    AUTHENTICATION_REQUIRED   - 0x%lx\n", AttributesSupported &
> IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);
> +  Print(L"  AttributesSetting           - 0x%lx\n", AttributesSetting);
> +  Print(L"    IMAGE_UPDATABLE           - 0x%lx\n", AttributesSetting &
> IMAGE_ATTRIBUTE_IMAGE_UPDATABLE);
> +  Print(L"    RESET_REQUIRED            - 0x%lx\n", AttributesSetting &
> IMAGE_ATTRIBUTE_RESET_REQUIRED);
> +  Print(L"    AUTHENTICATION_REQUIRED   - 0x%lx\n", AttributesSetting &
> IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);
> +}
> +
> +/**
> +  Dump FMP protocol info.
> +**/
> +VOID
> +DumpFmpData (
> +  VOID
> +  )
> +{
> +  EFI_STATUS                                    Status;
> +  EFI_FIRMWARE_MANAGEMENT_PROTOCOL              *Fmp;
> +  EFI_HANDLE                                    *HandleBuffer;
> +  UINTN                                         NumberOfHandles;
> +  UINTN                                         Index;
> +  EFI_FIRMWARE_IMAGE_DESCRIPTOR                 *FmpImageInfoBuf;
> +  UINTN                                         ImageInfoSize;
> +  UINT32                                        FmpImageInfoDescriptorVer;
> +  UINT8                                         FmpImageInfoCount;
> +  UINTN                                         DescriptorSize;
> +  UINT32                                        PackageVersion;
> +  CHAR16                                        *PackageVersionName;
> +  UINT32                                        PackageVersionNameMaxLen;
> +  UINT64                                        AttributesSupported;
> +  UINT64                                        AttributesSetting;
> +
> +  Print(L"############\n");
> +  Print(L"# FMP DATA #\n");
> +  Print(L"############\n");
> +  Status = gBS->LocateHandleBuffer (
> +                  ByProtocol,
> +                  &gEfiFirmwareManagementProtocolGuid,
> +                  NULL,
> +                  &NumberOfHandles,
> +                  &HandleBuffer
> +                  );
> +  if (EFI_ERROR(Status)) {
> +    Print(L"FMP protocol - %r\n", EFI_NOT_FOUND);
> +    return;
> +  }
> +
> +  for (Index = 0; Index < NumberOfHandles; Index++) {
> +    Status = gBS->HandleProtocol(
> +                    HandleBuffer[Index],
> +                    &gEfiFirmwareManagementProtocolGuid,
> +                    (VOID **)&Fmp
> +                    );
> +    if (EFI_ERROR(Status)) {
> +      continue;
> +    }
> +
> +    ImageInfoSize = 0;
> +    Status = Fmp->GetImageInfo (
> +                    Fmp,
> +                    &ImageInfoSize,
> +                    NULL,
> +                    NULL,
> +                    NULL,
> +                    NULL,
> +                    NULL,
> +                    NULL
> +                    );
> +    if (Status != EFI_BUFFER_TOO_SMALL) {
> +      continue;
> +    }
> +
> +    FmpImageInfoBuf = NULL;
> +    FmpImageInfoBuf = AllocateZeroPool (ImageInfoSize);
> +    if (FmpImageInfoBuf == NULL) {
> +      Status = EFI_OUT_OF_RESOURCES;
> +      goto EXIT;
> +    }
> +
> +    PackageVersionName = NULL;
> +    Status = Fmp->GetImageInfo (
> +                    Fmp,
> +                    &ImageInfoSize,               // ImageInfoSize
> +                    FmpImageInfoBuf,              // ImageInfo
> +                    &FmpImageInfoDescriptorVer,   // DescriptorVersion
> +                    &FmpImageInfoCount,           // DescriptorCount
> +                    &DescriptorSize,              // DescriptorSize
> +                    &PackageVersion,              // PackageVersion
> +                    &PackageVersionName           // PackageVersionName
> +                    );
> +
> +    //
> +    // If FMP GetInformation interface failed, skip this resource
> +    //
> +    if (EFI_ERROR(Status)) {
> +      Print(L"FMP (%d) ImageInfo - %r\n", Index, Status);
> +      FreePool(FmpImageInfoBuf);
> +      continue;
> +    }
> +
> +    Print(L"FMP (%d) ImageInfo:\n", Index);
> +    DumpFmpImageInfo(
> +      ImageInfoSize,               // ImageInfoSize
> +      FmpImageInfoBuf,             // ImageInfo
> +      FmpImageInfoDescriptorVer,   // DescriptorVersion
> +      FmpImageInfoCount,           // DescriptorCount
> +      DescriptorSize,              // DescriptorSize
> +      PackageVersion,              // PackageVersion
> +      PackageVersionName           // PackageVersionName
> +      );
> +
> +    if (PackageVersionName != NULL) {
> +      FreePool(PackageVersionName);
> +    }
> +    FreePool(FmpImageInfoBuf);
> +
> +    //
> +    // Get package info
> +    //
> +    PackageVersionName = NULL;
> +    Status = Fmp->GetPackageInfo (
> +                    Fmp,
> +                    &PackageVersion,              // PackageVersion
> +                    &PackageVersionName,          // PackageVersionName
> +                    &PackageVersionNameMaxLen,    // PackageVersionNameMaxLen
> +                    &AttributesSupported,         // AttributesSupported
> +                    &AttributesSetting            // AttributesSetting
> +                    );
> +    if (EFI_ERROR(Status)) {
> +      Print(L"FMP (%d) PackageInfo - %r\n", Index, Status);
> +    } else {
> +      Print(L"FMP (%d) ImageInfo:\n", Index);
> +      DumpFmpPackageInfo(
> +        PackageVersion,              // PackageVersion
> +        PackageVersionName,          // PackageVersionName
> +        PackageVersionNameMaxLen,    // PackageVersionNameMaxLen
> +        AttributesSupported,         // AttributesSupported
> +        AttributesSetting            // AttributesSetting
> +        );
> +
> +      if (PackageVersionName != NULL) {
> +        FreePool(PackageVersionName);
> +      }
> +    }
> +  }
> +  Print(L"\n");
> +
> +EXIT:
> +  FreePool(HandleBuffer);
> +}
> --
> 2.7.4.windows.1
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>
https://lists.01.org/mailman/listinfo/edk2-devel

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

* Re: [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application.
  2016-10-11  8:08                   ` Ni, Ruiyu
@ 2016-10-11  8:28                     ` Ni, Ruiyu
  2016-10-11  8:46                       ` Yao, Jiewen
  2016-10-11 14:44                       ` Yao, Jiewen
  0 siblings, 2 replies; 83+ messages in thread
From: Ni, Ruiyu @ 2016-10-11  8:28 UTC (permalink / raw)
  To: Carsey, Jaben, Rothman, Michael A, Yao, Jiewen, Kinney, Michael D,
	'edk2-devel@lists.01.org'
  Cc: Tian, Feng, Zhang, Chao B, Gao, Liming, Zeng, Star

Jaben,
The reason I propose to move the Shell protocol definitions to MdePkg is that all applications that wants to use the ARGV can use the ShellParameter protocol, without depending on ShellPkg.

Thanks/Ray

From: Ni, Ruiyu
Sent: Tuesday, October 11, 2016 4:08 PM
To: Carsey, Jaben <jaben.carsey@intel.com>; Rothman, Michael A <michael.a.rothman@intel.com>; Yao, Jiewen <jiewen.yao@intel.com>; Kinney, Michael D <michael.d.kinney@intel.com>; edk2-devel@lists.01.org
Cc: Tian, Feng <feng.tian@intel.com>; Zhang, Chao B <chao.b.zhang@intel.com>; Gao, Liming <liming.gao@intel.com>; Zeng, Star <star.zeng@intel.com>
Subject: RE: [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application.

Jaben,
How about moving the contents in ShellPkg\Include\Protocol\ to MdePkg\Include\Protocol\?
All industry standard protocols are defined in MdePkg, except the Shell related protocols.

Thanks/Ray

From: Carsey, Jaben
Sent: Tuesday, October 4, 2016 4:38 AM
To: Rothman, Michael A <michael.a.rothman@intel.com<mailto:michael.a.rothman@intel.com>>; Ni, Ruiyu <ruiyu.ni@intel.com<mailto:ruiyu.ni@intel.com>>; Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>; edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>
Cc: Tian, Feng <feng.tian@intel.com<mailto:feng.tian@intel.com>>; Zhang, Chao B <chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com>>; Gao, Liming <liming.gao@intel.com<mailto:liming.gao@intel.com>>; Zeng, Star <star.zeng@intel.com<mailto:star.zeng@intel.com>>; Carsey, Jaben <jaben.carsey@intel.com<mailto:jaben.carsey@intel.com>>
Subject: RE: [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application.

I don’t think that is what I meant.  It’s a string and a length, not a structure.

I mean clarify the following:

1)      Is the name of the binary itself in the LoadOptions string as the first option or not there at all?

2)      Then clarify that all Parameters are space delimited.

From: Rothman, Michael A
Sent: Monday, October 03, 2016 11:36 AM
To: Carsey, Jaben <jaben.carsey@intel.com<mailto:jaben.carsey@intel.com>>; Ni, Ruiyu <ruiyu.ni@intel.com<mailto:ruiyu.ni@intel.com>>; Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>; edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>
Cc: Tian, Feng <feng.tian@intel.com<mailto:feng.tian@intel.com>>; Zhang, Chao B <chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com>>; Gao, Liming <liming.gao@intel.com<mailto:liming.gao@intel.com>>; Zeng, Star <star.zeng@intel.com<mailto:star.zeng@intel.com>>; Rothman, Michael A <michael.a.rothman@intel.com<mailto:michael.a.rothman@intel.com>>
Subject: RE: [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application.
Importance: High

You mean update the LoadOptions reference to refer to the EFI_LOAD_OPTION structure? Because that’s in essence what it means.

Thanks,
Mike Rothman
(迈克 罗斯曼 / माइकल रोथ्मेन् / Михаил Ротман / משה רוטמן)
רועה עיקרי של חתולים

From: Carsey, Jaben
Sent: Friday, September 30, 2016 8:31 AM
To: Ni, Ruiyu <ruiyu.ni@intel.com<mailto:ruiyu.ni@intel.com>>; Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>; edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>; Rothman, Michael A <michael.a.rothman@intel.com<mailto:michael.a.rothman@intel.com>>
Cc: Tian, Feng <feng.tian@intel.com<mailto:feng.tian@intel.com>>; Zhang, Chao B <chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com>>; Gao, Liming <liming.gao@intel.com<mailto:liming.gao@intel.com>>; Zeng, Star <star.zeng@intel.com<mailto:star.zeng@intel.com>>; Carsey, Jaben <jaben.carsey@intel.com<mailto:jaben.carsey@intel.com>>
Subject: RE: [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application.

Mike Rothman,

Can we get LoadOptions and LoadOptionsSize clarified in the UEFI Spec?  This seems like a simple clarification and I would argue its needed.  The UEFI Shell is not the only producer of this protocol.  BDS launches things (like the UEFI Shell itself) and the shell already consumes it for itself (and it works).  I think it just needs clarification so people can depend on the current implementation not changing.

-Jaben

From: Ni, Ruiyu
Sent: Thursday, September 29, 2016 9:13 PM
To: Carsey, Jaben <jaben.carsey@intel.com<mailto:jaben.carsey@intel.com>>; Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>; edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>
Cc: Tian, Feng <feng.tian@intel.com<mailto:feng.tian@intel.com>>; Zhang, Chao B <chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com>>; Gao, Liming <liming.gao@intel.com<mailto:liming.gao@intel.com>>; Zeng, Star <star.zeng@intel.com<mailto:star.zeng@intel.com>>
Subject: RE: [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application.
Importance: High

Supposing user inputs “CapsuleApp.efi Parameter1 Parameter2”.
There is no spec to define what the LoadOption should equal to.
If there is another UEFI Shell implementation, it could interpret the command line then sets only “Parameter1 Parameter2” into LoadOption, or sets “CapsuleApp.efi\tParameter1\tParameter2” to LoadOption, or sets “[Shell]\tCapsuleApp.efi\tParameter1\tParameter2” to LoadOption.
Because it“produces” such LoadOption, it knows how to “consume”/parse it to get the ARGVs.

So I suggest we put the CapsuleApp in ShellPkg and let it use the ShellParameter protocol.

Regards,
Ray

From: Carsey, Jaben
Sent: Friday, September 30, 2016 3:11 AM
To: Ni, Ruiyu <ruiyu.ni@intel.com<mailto:ruiyu.ni@intel.com>>; Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>; edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>
Cc: Tian, Feng <feng.tian@intel.com<mailto:feng.tian@intel.com>>; Zhang, Chao B <chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com>>; Gao, Liming <liming.gao@intel.com<mailto:liming.gao@intel.com>>; Zeng, Star <star.zeng@intel.com<mailto:star.zeng@intel.com>>; Carsey, Jaben <jaben.carsey@intel.com<mailto:jaben.carsey@intel.com>>
Subject: RE: [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application.

I am confused.

Why is LoadOption and LoadOptionSize not working?  This is specified as part of UEFI Spec (Note: Not UEFI Shell Spec) as a standard way to pass parameters to UEFI appliations.  I think this should work (although it is more work than just examining argc/argv).

-Jaben

From: Ni, Ruiyu
Sent: Wednesday, September 28, 2016 11:40 PM
To: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>; edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>
Cc: Tian, Feng <feng.tian@intel.com<mailto:feng.tian@intel.com>>; Zhang, Chao B <chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com>>; Gao, Liming <liming.gao@intel.com<mailto:liming.gao@intel.com>>; Zeng, Star <star.zeng@intel.com<mailto:star.zeng@intel.com>>; Carsey, Jaben <jaben.carsey@intel.com<mailto:jaben.carsey@intel.com>>
Subject: RE: [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application.
Importance: High

Jiewen,
The way CapsuleApp extracts the ARGV assumes UEFI Shell encodes the parameters using a certain way. But the parameter encoding way is not described in the Shell spec.
Maybe we can put the CapsuleApp in ShellPkg, then let it directly use ShellParameter protocol to get the ARGV.

Copying Jaben.

Regards,
Ray

From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of Yao, Jiewen
Sent: Thursday, September 29, 2016 10:37 AM
To: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>; edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>
Cc: Tian, Feng <feng.tian@intel.com<mailto:feng.tian@intel.com>>; Zhang, Chao B <chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com>>; Gao, Liming <liming.gao@intel.com<mailto:liming.gao@intel.com>>; Zeng, Star <star.zeng@intel.com<mailto:star.zeng@intel.com>>
Subject: Re: [edk2] [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application.

Right. CapsuleOnDisk is not supported in BIOS yet.
I will remove it in CapsuleApp.

CapsuleApp just works as an agent to pass capsule to CapsuleDxeRuntime driver.
So it is checked by CapsuleDxeRuntime, not CapsuleApp.

Thank you
Yao Jiewen

From: Kinney, Michael D
Sent: Thursday, September 29, 2016 9:06 AM
To: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>; Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>
Cc: Tian, Feng <feng.tian@intel.com<mailto:feng.tian@intel.com>>; Zeng, Star <star.zeng@intel.com<mailto:star.zeng@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: [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application.

Jiewen,

Does the capsule on disk feature provided by this app work?

I tried it with the QuarkPlatformPkg capsule and I can get
The app to copy the capsule to an EFI System Partition, but
The logic after that point looks incomplete.

Also, if I clear the Persist and Reset flags on the capsule,
the immediate processing of the capsule does not work.

Is there any FW code that will look for capsules on disk?

If there are incomplete features in CapsuleApp, then I think
we should remove them.

Mike

> -----Original Message-----
> From: Yao, Jiewen
> Sent: Tuesday, September 20, 2016 11:45 PM
> To: edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org%3cmailto:edk2-devel@lists.01.org>>
> Cc: Tian, Feng <feng.tian@intel.com<mailto:feng.tian@intel.com<mailto:feng.tian@intel.com%3cmailto:feng.tian@intel.com>>>; Zeng, Star <star.zeng@intel.com<mailto:star.zeng@intel.com<mailto:star.zeng@intel.com%3cmailto:star.zeng@intel.com>>>; Kinney, Michael
> D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com%3cmailto:michael.d.kinney@intel.com>>>; Gao, Liming <liming.gao@intel.com<mailto:liming.gao@intel.com<mailto:liming.gao@intel.com%3cmailto:liming.gao@intel.com>>>; Zhang, Chao B
> <chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com%3cmailto:chao.b.zhang@intel.com>>>
> Subject: [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application.
>
> This CapsuleApp can help perform capsule update in UEFI shell environment.
> It can also dump capsule information, capsule status variable, ESRT and FMP.
>
> Cc: Feng Tian <feng.tian@intel.com<mailto:feng.tian@intel.com<mailto:feng.tian@intel.com%3cmailto:feng.tian@intel.com>>>
> Cc: Star Zeng <star.zeng@intel.com<mailto:star.zeng@intel.com<mailto:star.zeng@intel.com%3cmailto:star.zeng@intel.com>>>
> Cc: Michael D Kinney <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com%3cmailto:michael.d.kinney@intel.com>>>
> Cc: Liming Gao <liming.gao@intel.com<mailto:liming.gao@intel.com<mailto:liming.gao@intel.com%3cmailto:liming.gao@intel.com>>>
> Cc: Chao Zhang <chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com%3cmailto:chao.b.zhang@intel.com>>>
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Jiewen Yao <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com<mailto:jiewen.yao@intel.com%3cmailto:jiewen.yao@intel.com>>>
> ---
>  MdeModulePkg/Application/CapsuleApp/AppSupport.c        |  480 +++++++++
>  MdeModulePkg/Application/CapsuleApp/CapsuleApp.c        | 1047 ++++++++++++++++++++
>  MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf      |   71 ++
>  MdeModulePkg/Application/CapsuleApp/CapsuleApp.uni      |   22 +
>  MdeModulePkg/Application/CapsuleApp/CapsuleAppExtra.uni |   19 +
>  MdeModulePkg/Application/CapsuleApp/CapsuleDump.c       |  840 ++++++++++++++++
>  6 files changed, 2479 insertions(+)
>
> diff --git a/MdeModulePkg/Application/CapsuleApp/AppSupport.c
> b/MdeModulePkg/Application/CapsuleApp/AppSupport.c
> new file mode 100644
> index 0000000..365067d
> --- /dev/null
> +++ b/MdeModulePkg/Application/CapsuleApp/AppSupport.c
> @@ -0,0 +1,480 @@
> +/** @file
> +  A shell application that triggers capsule update process.
> +
> +  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the BSD License
> +  which accompanies this distribution.  The full text of the license may be found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +
> +**/
> +
> +#include <Uefi.h>
> +#include <Library/BaseLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/UefiRuntimeServicesTableLib.h>
> +#include <Library/UefiLib.h>
> +#include <Library/PrintLib.h>
> +#include <Protocol/LoadedImage.h>
> +#include <Protocol/SimpleFileSystem.h>
> +#include <Guid/FileInfo.h>
> +#include <Guid/Gpt.h>
> +
> +#define MAX_ARG_NUM     11
> +
> +UINTN  Argc = 0;
> +CHAR16 *Argv[MAX_ARG_NUM];
> +CHAR16 *ArgBuffer;
> +
> +/**
> +
> +  This function parse application ARG.
> +
> +  @return Status
> +**/
> +EFI_STATUS
> +GetArg (
> +  VOID
> +  )
> +{
> +  UINT8                         *Data;
> +  UINTN                         DataSize;
> +  CHAR16                        *Index;
> +  CHAR16                        *End;
> +  CHAR16                        *DIndex;
> +  EFI_STATUS                    Status;
> +  EFI_LOADED_IMAGE_PROTOCOL     *LoadedImage;
> +
> +  Status = gBS->HandleProtocol (
> +                  gImageHandle,
> +                  &gEfiLoadedImageProtocolGuid,
> +                  (VOID**)&LoadedImage
> +                  );
> +  if (EFI_ERROR(Status)) {
> +    return Status;
> +  }
> +
> +  Data = LoadedImage->LoadOptions;
> +  DataSize = LoadedImage->LoadOptionsSize;
> +
> +  End = (CHAR16*)(UINTN)(Data + DataSize);
> +  Status = gBS->AllocatePool (EfiBootServicesData, DataSize, (VOID **)&ArgBuffer);
> +  ASSERT_EFI_ERROR (Status);
> +  DIndex = ArgBuffer;
> +  Argv[Argc++] = ArgBuffer;
> +  for (Index = (CHAR16*)Data; Index < End; ) {
> +    if (*Index == L' ') {
> +      *DIndex = L'\0';
> +      if (Argc >= MAX_ARG_NUM) {
> +        return EFI_UNSUPPORTED;
> +      }
> +      Argv[Argc++] = (++ DIndex);
> +      while(*Index == L' ') {
> +        Index ++;
> +      }
> +    }
> +    (*(DIndex ++)) = (*(Index ++));
> +  }
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Clear APP ARG.
> +**/
> +VOID
> +CleanArg (
> +  VOID
> +  )
> +{
> +  FreePool (Argv[0]);
> +}
> +
> +/**
> +  Return File System Volume containing this shell application.
> +
> +  @return File System Volume containing this shell application.
> +**/
> +EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *
> +GetMyVol (
> +  VOID
> +  )
> +{
> +  EFI_STATUS                        Status;
> +  EFI_LOADED_IMAGE_PROTOCOL         *LoadedImage;
> +  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Vol;
> +
> +  Status = gBS->HandleProtocol (
> +                  gImageHandle,
> +                  &gEfiLoadedImageProtocolGuid,
> +                  (VOID **)&LoadedImage
> +                  );
> +  ASSERT_EFI_ERROR (Status);
> +
> +  Status = gBS->HandleProtocol (
> +                  LoadedImage->DeviceHandle,
> +                  &gEfiSimpleFileSystemProtocolGuid,
> +                  (VOID **)&Vol
> +                  );
> +  if (!EFI_ERROR (Status)) {
> +    return Vol;
> +  }
> +
> +  return NULL;
> +}
> +
> +/**
> +  Read a file from this volume.
> +
> +  @param Vol             File System Volume
> +  @param FileName        The file to be read.
> +  @param BufferSize      The file buffer size
> +  @param Buffer          The file buffer
> +
> +  @retval EFI_SUCCESS    Read file successfully
> +  @retval EFI_NOT_FOUND  File not found
> +**/
> +EFI_STATUS
> +ReadFileFromVol (
> +  IN  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Vol,
> +  IN  CHAR16                            *FileName,
> +  OUT UINTN                             *BufferSize,
> +  OUT VOID                              **Buffer
> +  )
> +{
> +  EFI_STATUS                        Status;
> +  EFI_FILE_HANDLE                   RootDir;
> +  EFI_FILE_HANDLE                   Handle;
> +  UINTN                             FileInfoSize;
> +  EFI_FILE_INFO                     *FileInfo;
> +  UINTN                             TempBufferSize;
> +  VOID                              *TempBuffer;
> +
> +  //
> +  // Open the root directory
> +  //
> +  Status = Vol->OpenVolume (Vol, &RootDir);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  //
> +  // Open the file
> +  //
> +  Status = RootDir->Open (
> +                      RootDir,
> +                      &Handle,
> +                      FileName,
> +                      EFI_FILE_MODE_READ,
> +                      0
> +                      );
> +  if (EFI_ERROR (Status)) {
> +    RootDir->Close (RootDir);
> +    return Status;
> +  }
> +
> +  RootDir->Close (RootDir);
> +
> +  //
> +  // Get the file information
> +  //
> +  FileInfoSize = sizeof(EFI_FILE_INFO) + 1024;
> +
> +  FileInfo = AllocateZeroPool (FileInfoSize);
> +  if (FileInfo == NULL) {
> +    Handle->Close (Handle);
> +    return Status;
> +  }
> +
> +  Status = Handle->GetInfo (
> +                     Handle,
> +                     &gEfiFileInfoGuid,
> +                     &FileInfoSize,
> +                     FileInfo
> +                     );
> +  if (EFI_ERROR (Status)) {
> +    Handle->Close (Handle);
> +    gBS->FreePool (FileInfo);
> +    return Status;
> +  }
> +
> +  //
> +  // Allocate buffer for the file data. The last CHAR16 is for L'\0'
> +  //
> +  TempBufferSize = (UINTN) FileInfo->FileSize + sizeof(CHAR16);
> +  TempBuffer = AllocateZeroPool (TempBufferSize);
> +  if (TempBuffer == NULL) {
> +    Handle->Close (Handle);
> +    gBS->FreePool (FileInfo);
> +    return Status;
> +  }
> +
> +  gBS->FreePool (FileInfo);
> +
> +  //
> +  // Read the file data to the buffer
> +  //
> +  Status = Handle->Read (
> +                     Handle,
> +                     &TempBufferSize,
> +                     TempBuffer
> +                     );
> +  if (EFI_ERROR (Status)) {
> +    Handle->Close (Handle);
> +    gBS->FreePool (TempBuffer);
> +    return Status;
> +  }
> +
> +  Handle->Close (Handle);
> +
> +  *BufferSize = TempBufferSize;
> +  *Buffer     = TempBuffer;
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Read a file.
> +  If ScanFs is FLASE, it will use this Vol as default Fs.
> +  If ScanFs is TRUE, it will scan all FS and check the file.
> +    If there is only one file match the name, it will be read.
> +    If there is more than one file match the name, it will return Error.
> +
> +  @param ThisVol         File System Volume
> +  @param FileName        The file to be read.
> +  @param BufferSize      The file buffer size
> +  @param Buffer          The file buffer
> +  @param ScanFs          Need Scan all FS
> +
> +  @retval EFI_SUCCESS    Read file successfully
> +  @retval EFI_NOT_FOUND  File not found
> +  @retval EFI_NO_MAPPING There is duplicated files found
> +**/
> +EFI_STATUS
> +ReadFileToBufferEx (
> +  IN OUT EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   **ThisVol,
> +  IN  CHAR16                               *FileName,
> +  OUT UINTN                                *BufferSize,
> +  OUT VOID                                 **Buffer,
> +  IN  BOOLEAN                              ScanFs
> +  )
> +{
> +  EFI_STATUS                        Status;
> +  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Vol;
> +  UINTN                             TempBufferSize;
> +  VOID                              *TempBuffer;
> +  UINTN                             NoHandles;
> +  EFI_HANDLE                        *HandleBuffer;
> +  UINTN                             Index;
> +
> +  //
> +  // Check parameters
> +  //
> +  if ((FileName == NULL) || (Buffer == NULL) || (ThisVol == NULL)) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  //
> +  // not scan fs
> +  //
> +  if (!ScanFs) {
> +    if (*ThisVol == NULL) {
> +      *ThisVol = GetMyVol ();
> +      if (*ThisVol == NULL) {
> +        return EFI_INVALID_PARAMETER;
> +      }
> +    }
> +    //
> +    // Read file directly from Vol
> +    //
> +    return ReadFileFromVol (*ThisVol, FileName, BufferSize, Buffer);
> +  }
> +
> +  //
> +  // need scan fs
> +  //
> +
> +  //
> +  // Get all Vol handle
> +  //
> +  Status = gBS->LocateHandleBuffer (
> +                   ByProtocol,
> +                   &gEfiSimpleFileSystemProtocolGuid,
> +                   NULL,
> +                   &NoHandles,
> +                   &HandleBuffer
> +                   );
> +  if (EFI_ERROR (Status) && (NoHandles == 0)) {
> +    return EFI_NOT_FOUND;
> +  }
> +
> +  //
> +  // Walk through each Vol
> +  //
> +  *ThisVol = NULL;
> +  *BufferSize = 0;
> +  *Buffer     = NULL;
> +  for (Index = 0; Index < NoHandles; Index++) {
> +    Status = gBS->HandleProtocol (
> +                    HandleBuffer[Index],
> +                    &gEfiSimpleFileSystemProtocolGuid,
> +                    (VOID **)&Vol
> +                    );
> +    if (EFI_ERROR(Status)) {
> +      continue;
> +    }
> +
> +    Status = ReadFileFromVol (Vol, FileName, &TempBufferSize, &TempBuffer);
> +    if (!EFI_ERROR (Status)) {
> +      //
> +      // Read file OK, check duplication
> +      //
> +      if (*ThisVol != NULL) {
> +        //
> +        // Find the duplicated file
> +        //
> +        gBS->FreePool (TempBuffer);
> +        gBS->FreePool (*Buffer);
> +        Print (L"Duplicated FileName found!\n");
> +        return EFI_NO_MAPPING;
> +      } else {
> +        //
> +        // Record value
> +        //
> +        *ThisVol = Vol;
> +        *BufferSize = TempBufferSize;
> +        *Buffer     = TempBuffer;
> +      }
> +    }
> +  }
> +
> +  //
> +  // Scan Fs done
> +  //
> +  if (*ThisVol == NULL) {
> +    return EFI_NOT_FOUND;
> +  }
> +
> +  //
> +  // Done
> +  //
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Read a file.
> +
> +  @param FileName        The file to be read.
> +  @param BufferSize      The file buffer size
> +  @param Buffer          The file buffer
> +
> +  @retval EFI_SUCCESS    Read file successfully
> +  @retval EFI_NOT_FOUND  File not found
> +**/
> +EFI_STATUS
> +ReadFileToBuffer (
> +  IN  CHAR16                               *FileName,
> +  OUT UINTN                                *BufferSize,
> +  OUT VOID                                 **Buffer
> +  )
> +{
> +  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Vol;
> +  Vol = NULL;
> +  return ReadFileToBufferEx(&Vol, FileName, BufferSize, Buffer, FALSE);
> +}
> +
> +/**
> +  Write a file.
> +
> +  @param FileName        The file to be written.
> +  @param BufferSize      The file buffer size
> +  @param Buffer          The file buffer
> +
> +  @retval EFI_SUCCESS    Write file successfully
> +**/
> +EFI_STATUS
> +WriteFileFromBuffer(
> +  IN  CHAR16                               *FileName,
> +  IN  UINTN                                BufferSize,
> +  IN  VOID                                 *Buffer
> +  )
> +{
> +  EFI_STATUS                        Status;
> +  EFI_FILE_HANDLE                   RootDir;
> +  EFI_FILE_HANDLE                   Handle;
> +  UINTN                             TempBufferSize;
> +  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Vol;
> +
> +  Vol = GetMyVol();
> +
> +  //
> +  // Open the root directory
> +  //
> +  Status = Vol->OpenVolume (Vol, &RootDir);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  //
> +  // Open the file
> +  //
> +  Status = RootDir->Open (
> +                      RootDir,
> +                      &Handle,
> +                      FileName,
> +                      EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE| EFI_FILE_MODE_CREATE,
> +                      0
> +                      );
> +  if (EFI_ERROR (Status)) {
> +    RootDir->Close (RootDir);
> +    return Status;
> +  }
> +
> +  //
> +  // Delete file
> +  //
> +  Status = Handle->Delete(Handle);
> +  if (EFI_ERROR(Status)) {
> +    return Status;
> +  }
> +
> +  //
> +  // Open the file again
> +  //
> +  Status = RootDir->Open (
> +                      RootDir,
> +                      &Handle,
> +                      FileName,
> +                      EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE| EFI_FILE_MODE_CREATE,
> +                      0
> +                      );
> +  if (EFI_ERROR (Status)) {
> +    RootDir->Close (RootDir);
> +    return Status;
> +  }
> +
> +  RootDir->Close (RootDir);
> +
> +  //
> +  // Write the file data from the buffer
> +  //
> +  TempBufferSize = BufferSize;
> +  Status = Handle->Write (
> +                     Handle,
> +                     &TempBufferSize,
> +                     Buffer
> +                     );
> +  if (EFI_ERROR (Status)) {
> +    Handle->Close (Handle);
> +    return Status;
> +  }
> +
> +  Handle->Close (Handle);
> +
> +  return EFI_SUCCESS;
> +}
> +
> diff --git a/MdeModulePkg/Application/CapsuleApp/CapsuleApp.c
> b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.c
> new file mode 100644
> index 0000000..0a28557
> --- /dev/null
> +++ b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.c
> @@ -0,0 +1,1047 @@
> +/** @file
> +  A shell application that triggers capsule update process.
> +
> +  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the BSD License
> +  which accompanies this distribution.  The full text of the license may be found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +
> +**/
> +
> +#include <Uefi.h>
> +#include <Library/BaseLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/UefiRuntimeServicesTableLib.h>
> +#include <Library/UefiLib.h>
> +#include <Library/PrintLib.h>
> +#include <Protocol/LoadedImage.h>
> +#include <Protocol/SimpleFileSystem.h>
> +#include <Protocol/GraphicsOutput.h>
> +#include <Guid/FileInfo.h>
> +#include <Guid/Gpt.h>
> +#include <Guid/GlobalVariable.h>
> +#include <Guid/CapsuleReport.h>
> +#include <Guid/SystemResourceTable.h>
> +#include <Guid/FmpCapsule.h>
> +#include <IndustryStandard/WindowsUxCapsule.h>
> +
> +#define CAPSULE_HEADER_SIZE  0x20
> +
> +#define NESTED_CAPSULE_HEADER_SIZE  SIZE_4KB
> +#define SYSTEM_FIRMWARE_FLAG 0x50000
> +#define DEVICE_FIRMWARE_FLAG 0x78010
> +
> +#define EFI_CAPSULE_FROM_FILE_DIR                           L"\\EFI\\UpdateCapsule\\<file:///\\EFI\UpdateCapsule\><file://EFI/UpdateCapsule/%3cfile:/EFI/UpdateCapsule/%3e>"
> +#define EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED  0x0000000000000004
> +
> +#define MAJOR_VERSION   1
> +#define MINOR_VERSION   0
> +
> +#define MAX_ARG_NUM     11
> +#define MAX_CAPSULE_NUM (MAX_ARG_NUM - 1)
> +
> +extern UINTN  Argc;
> +extern CHAR16 *Argv[];
> +
> +//
> +// Define how many block descriptors we want to test with.
> +//
> +UINTN  NumberOfDescriptors = 1;
> +UINTN  CapsuleFirstIndex;
> +UINTN  CapsuleLastIndex;
> +
> +/**
> +  Dump capsule information
> +
> +  @retval EFI_SUCCESS            The capsule information is dumped.
> +  @retval EFI_UNSUPPORTED        Input parameter is not valid.
> +**/
> +EFI_STATUS
> +DumpCapsule(
> +  VOID
> +  );
> +
> +/**
> +  Dump capsule status variable.
> +
> +  @retval EFI_SUCCESS            The capsule status variable is dumped.
> +  @retval EFI_UNSUPPORTED        Input parameter is not valid.
> +**/
> +EFI_STATUS
> +DmpCapsuleStatusVariable(
> +  VOID
> +  );
> +
> +/**
> +  Dump FMP protocol info.
> +**/
> +VOID
> +DumpFmpData(
> +  VOID
> +  );
> +
> +/**
> +  Dump ESRT info.
> +**/
> +VOID
> +DumpEsrtData(
> +  VOID
> +  );
> +
> +/**
> +  Read a file.
> +
> +  @param FileName        The file to be read.
> +  @param BufferSize      The file buffer size
> +  @param Buffer          The file buffer
> +
> +  @retval EFI_SUCCESS    Read file successfully
> +  @retval EFI_NOT_FOUND  File not found
> +**/
> +EFI_STATUS
> +ReadFileToBuffer(
> +  IN  CHAR16                               *FileName,
> +  OUT UINTN                                *BufferSize,
> +  OUT VOID                                 **Buffer
> +  );
> +
> +/**
> +  Write a file.
> +
> +  @param FileName        The file to be written.
> +  @param BufferSize      The file buffer size
> +  @param Buffer          The file buffer
> +
> +  @retval EFI_SUCCESS    Write file successfully
> +**/
> +EFI_STATUS
> +WriteFileFromBuffer(
> +  IN  CHAR16                               *FileName,
> +  IN  UINTN                                BufferSize,
> +  IN  VOID                                 *Buffer
> +  );
> +
> +/**
> +
> +  This function parse application ARG.
> +
> +  @return Status
> +**/
> +EFI_STATUS
> +GetArg (
> +  VOID
> +  );
> +
> +/**
> +  Clear APP ARG.
> +**/
> +VOID
> +CleanArg (
> +  VOID
> +  );
> +
> +/**
> +  Create UX capsule.
> +
> +  @retval EFI_SUCCESS            The capsule header is appended.
> +  @retval EFI_UNSUPPORTED        Input parameter is not valid.
> +  @retval EFI_OUT_OF_RESOURCES   No enough resource to create UX capsule.
> +**/
> +EFI_STATUS
> +CreateBmpFmp(
> +  VOID
> +  )
> +{
> +  CHAR16                                        *OutputCapsuleName;
> +  VOID                                          *BmpBuffer;
> +  UINTN                                         FileSize;
> +  CHAR16                                        *BmpName;
> +  UINT8                                         *FullCapsuleBuffer;
> +  UINTN                                         FullCapsuleBufferSize;
> +  EFI_DISPLAY_CAPSULE                           *DisplayCapsule;
> +  EFI_STATUS                                    Status;
> +  EFI_GRAPHICS_OUTPUT_PROTOCOL                  *Gop;
> +
> +  Status = gBS->LocateProtocol(&gEfiGraphicsOutputProtocolGuid, NULL, (VOID **)&Gop);
> +  if (EFI_ERROR(Status)) {
> +    Print(L"CapsuleApp: NO GOP is found.\n");
> +    return EFI_UNSUPPORTED;
> +  }
> +  Print(L"Current GOP: Mode - %d, ", Gop->Mode->Mode);
> +  Print(L"HorizontalResolution - %d, ", Gop->Mode->Info->HorizontalResolution);
> +  Print(L"VerticalResolution - %d\n", Gop->Mode->Info->VerticalResolution);
> +  // HorizontalResolution >= BMP_IMAGE_HEADER.PixelWidth
> +  // VerticalResolution   >= BMP_IMAGE_HEADER.PixelHeight
> +
> +  if (Argc != 5) {
> +    Print(L"CapsuleApp: Invalid Parameter.\n");
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  if (StrCmp(Argv[3], L"-O") != 0) {
> +    Print(L"CapsuleApp: NO output capsule name.\n");
> +    return EFI_UNSUPPORTED;
> +  }
> +  OutputCapsuleName = Argv[4];
> +
> +  BmpBuffer = NULL;
> +  FileSize = 0;
> +  FullCapsuleBuffer = NULL;
> +
> +  BmpName = Argv[2];
> +  Status = ReadFileToBuffer(BmpName, &FileSize, &BmpBuffer);
> +  if (EFI_ERROR(Status)) {
> +    Print(L"CapsuleApp: BMP image (%s) is not found.\n", BmpName);
> +    goto Done;
> +  }
> +
> +  FullCapsuleBufferSize = sizeof(EFI_DISPLAY_CAPSULE) + FileSize;
> +  FullCapsuleBuffer = AllocatePool(FullCapsuleBufferSize);
> +  if (FullCapsuleBuffer == NULL) {
> +    Print(L"CapsuleApp: Capsule Buffer size (0x%x) too big.\n",
> FullCapsuleBufferSize);
> +    Status = EFI_OUT_OF_RESOURCES;
> +    goto Done;
> +  }
> +
> +  DisplayCapsule = (EFI_DISPLAY_CAPSULE *)FullCapsuleBuffer;
> +  CopyGuid(&DisplayCapsule->CapsuleHeader.CapsuleGuid, &gWindowsUxCapsuleGuid);
> +  DisplayCapsule->CapsuleHeader.HeaderSize = sizeof(DisplayCapsule->CapsuleHeader);
> +  DisplayCapsule->CapsuleHeader.Flags = CAPSULE_FLAGS_PERSIST_ACROSS_RESET;
> +  DisplayCapsule->CapsuleHeader.CapsuleImageSize = (UINT32)FullCapsuleBufferSize;
> +
> +  DisplayCapsule->ImagePayload.Version = 1;
> +  DisplayCapsule->ImagePayload.Checksum = 0;
> +  DisplayCapsule->ImagePayload.ImageType = 0; // BMP
> +  DisplayCapsule->ImagePayload.Reserved = 0;
> +  DisplayCapsule->ImagePayload.Mode = Gop->Mode->Mode;
> +  DisplayCapsule->ImagePayload.OffsetX = 0;
> +  DisplayCapsule->ImagePayload.OffsetY = 0;
> +
> +  CopyMem((DisplayCapsule + 1), BmpBuffer, FileSize);
> +
> +  DisplayCapsule->ImagePayload.Checksum = CalculateCheckSum8(FullCapsuleBuffer,
> FullCapsuleBufferSize);
> +
> +  Status = WriteFileFromBuffer(OutputCapsuleName, FullCapsuleBufferSize,
> FullCapsuleBuffer);
> +  Print(L"CapsuleApp: Write %s %r\n", OutputCapsuleName, Status);
> +
> +Done:
> +  if (BmpBuffer != NULL) {
> +    FreePool(BmpBuffer);
> +  }
> +
> +  if (FullCapsuleBuffer != NULL) {
> +    FreePool(FullCapsuleBuffer);
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  Get ImageTypeId in the FMP capsule header.
> +
> +  @param CapsuleHeader  The FMP capsule image header.
> +
> +  @return ImageTypeId
> +**/
> +EFI_GUID *
> +GetCapsuleImageTypeId(
> +  IN EFI_CAPSULE_HEADER                            *CapsuleHeader
> +  )
> +{
> +  EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER       *FmpCapsuleHeader;
> +  UINT64                                       *ItemOffsetList;
> +  EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader;
> +
> +  FmpCapsuleHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *)((UINT8 *)CapsuleHeader
> + CapsuleHeader->HeaderSize);
> +  ItemOffsetList = (UINT64 *)(FmpCapsuleHeader + 1);
> +  if (FmpCapsuleHeader->PayloadItemCount == 0) {
> +    return NULL;
> +  }
> +  ImageHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *)((UINT8
> *)FmpCapsuleHeader + ItemOffsetList[FmpCapsuleHeader->EmbeddedDriverCount]);
> +  return &ImageHeader->UpdateImageTypeId;
> +}
> +
> +/**
> +  Get ESRT FwType according to ImageTypeId
> +
> +  @param  ImageTypeId   ImageTypeId of an FMP capsule.
> +
> +  @return ESRT FwType
> +**/
> +UINT32
> +GetEsrtFwType(
> +  IN  EFI_GUID                                      *ImageTypeId
> +  )
> +{
> +  EFI_STATUS                 Status;
> +  EFI_SYSTEM_RESOURCE_TABLE  *Esrt;
> +  EFI_SYSTEM_RESOURCE_ENTRY  *EsrtEntry;
> +  UINTN                      Index;
> +
> +  //
> +  // Check ESRT
> +  //
> +  Status = EfiGetSystemConfigurationTable(&gEfiSystemResourceTableGuid, (VOID
> **)&Esrt);
> +  if (!EFI_ERROR(Status)) {
> +    EsrtEntry = (VOID *)(Esrt + 1);
> +    for (Index = 0; Index < Esrt->FwResourceCount; Index++, EsrtEntry++) {
> +      if (CompareGuid(&EsrtEntry->FwClass, ImageTypeId)) {
> +        return EsrtEntry->FwType;
> +      }
> +    }
> +  }
> +
> +  return ESRT_FW_TYPE_UNKNOWN;
> +}
> +
> +/**
> +  Append a capsule header on top of current image.
> +  This function follows Windows UEFI Firmware Update Platform document.
> +
> +  @retval EFI_SUCCESS            The capsule header is appended.
> +  @retval EFI_UNSUPPORTED        Input parameter is not valid.
> +  @retval EFI_OUT_OF_RESOURCES   No enough resource to append capsule header.
> +**/
> +EFI_STATUS
> +CreateNestedFmp(
> +  VOID
> +  )
> +{
> +  CHAR16                                        *OutputCapsuleName;
> +  VOID                                          *CapsuleBuffer;
> +  UINTN                                         FileSize;
> +  CHAR16                                        *CapsuleName;
> +  UINT8                                         *FullCapsuleBuffer;
> +  UINTN                                         FullCapsuleBufferSize;
> +  EFI_CAPSULE_HEADER                            *NestedCapsuleHeader;
> +  EFI_GUID                                      *ImageTypeId;
> +  UINT32                                        FwType;
> +  EFI_STATUS                                    Status;
> +
> +  if (Argc != 5) {
> +    Print(L"CapsuleApp: Invalid Parameter.\n");
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  if (StrCmp(Argv[3], L"-O") != 0) {
> +    Print(L"CapsuleApp: NO output capsule name.\n");
> +    return EFI_UNSUPPORTED;
> +  }
> +  OutputCapsuleName = Argv[4];
> +
> +  CapsuleBuffer = NULL;
> +  FileSize = 0;
> +  FullCapsuleBuffer = NULL;
> +
> +  CapsuleName = Argv[2];
> +  Status = ReadFileToBuffer(CapsuleName, &FileSize, &CapsuleBuffer);
> +  if (EFI_ERROR(Status)) {
> +    Print(L"CapsuleApp: Capsule image (%s) is not found.\n", CapsuleName);
> +    goto Done;
> +  }
> +
> +  ImageTypeId = GetCapsuleImageTypeId(CapsuleBuffer);
> +  if (ImageTypeId == NULL) {
> +    Print(L"CapsuleApp: Capsule ImageTypeId is not found.\n");
> +    goto Done;
> +  }
> +  FwType = GetEsrtFwType(ImageTypeId);
> +  if ((FwType != ESRT_FW_TYPE_SYSTEMFIRMWARE) && (FwType !=
> ESRT_FW_TYPE_DEVICEFIRMWARE)) {
> +    Print(L"CapsuleApp: Capsule FwType is invalid.\n");
> +    goto Done;
> +  }
> +
> +  FullCapsuleBufferSize = NESTED_CAPSULE_HEADER_SIZE + FileSize;
> +  FullCapsuleBuffer = AllocatePool(FullCapsuleBufferSize);
> +  if (FullCapsuleBuffer == NULL) {
> +    Print(L"CapsuleApp: Capsule Buffer size (0x%x) too big.\n",
> FullCapsuleBufferSize);
> +    Status = EFI_OUT_OF_RESOURCES;
> +    goto Done;
> +  }
> +
> +  NestedCapsuleHeader = (EFI_CAPSULE_HEADER *)FullCapsuleBuffer;
> +  ZeroMem(NestedCapsuleHeader, NESTED_CAPSULE_HEADER_SIZE);
> +  CopyGuid(&NestedCapsuleHeader->CapsuleGuid, ImageTypeId);
> +  NestedCapsuleHeader->HeaderSize = NESTED_CAPSULE_HEADER_SIZE;
> +  NestedCapsuleHeader->Flags = (FwType == ESRT_FW_TYPE_DEVICEFIRMWARE) ?
> SYSTEM_FIRMWARE_FLAG : DEVICE_FIRMWARE_FLAG;
> +  NestedCapsuleHeader->CapsuleImageSize = (UINT32)FullCapsuleBufferSize;
> +
> +  CopyMem((UINT8 *)NestedCapsuleHeader + NestedCapsuleHeader->HeaderSize,
> CapsuleBuffer, FileSize);
> +
> +  Status = WriteFileFromBuffer(OutputCapsuleName, FullCapsuleBufferSize,
> FullCapsuleBuffer);
> +  Print(L"CapsuleApp: Write %s %r\n", OutputCapsuleName, Status);
> +
> +Done:
> +  if (CapsuleBuffer != NULL) {
> +    FreePool(CapsuleBuffer);
> +  }
> +
> +  if (FullCapsuleBuffer != NULL) {
> +    FreePool(FullCapsuleBuffer);
> +  }
> +
> +  return Status;
> +}
> +
> +
> +/**
> +  Clear capsule status variable.
> +
> +  @retval EFI_SUCCESS            The capsule status variable is cleared.
> +**/
> +EFI_STATUS
> +ClearCapsuleStatusVariable(
> +  VOID
> +  )
> +{
> +  EFI_STATUS                          Status;
> +  UINT32                              Index;
> +  CHAR16                              CapsuleVarName[20];
> +  CHAR16                              *TempVarName;
> +
> +  StrCpyS (CapsuleVarName, sizeof(CapsuleVarName)/sizeof(CapsuleVarName[0]),
> L"Capsule");
> +  TempVarName = CapsuleVarName + StrLen (CapsuleVarName);
> +  Index = 0;
> +
> +  while (TRUE) {
> +    UnicodeSPrint (TempVarName, 5 * sizeof(CHAR16), L"%04x", Index);
> +
> +    Status = gRT->SetVariable (
> +                    CapsuleVarName,
> +                    &gEfiCapsuleReportGuid,
> +                    EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS |
> EFI_VARIABLE_BOOTSERVICE_ACCESS,
> +                    0,
> +                    (VOID *)NULL
> +                    );
> +    if (EFI_ERROR(Status)) {
> +      //
> +      // There is no capsule variables, quit
> +      //
> +      break;
> +    }
> +
> +    Index++;
> +    if (Index > 0xFFFF) {
> +      break;
> +    }
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Get the active UEFI system partition from bootoption list.
> +
> +  @param[out] Fs    Simple File System protocol on the active UEFI system partition
> +
> +  @retval EFI_SUCCESS   active UEFI system partition found
> +**/
> +EFI_STATUS
> +GetEfiSysPartition(
> +  OUT EFI_SIMPLE_FILE_SYSTEM_PROTOCOL **Fs
> +  )
> +{
> +  EFI_STATUS                       Status;
> +  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL  *FsTemp;
> +  UINTN                            NoHandles;
> +  EFI_HANDLE                       *Handles;
> +  UINTN                            Index;
> +
> +  Handles = NULL;
> +
> +  //
> +  // search for EFI system partition protocol on Boot option device path
> +  //
> +  Status = gBS->LocateHandleBuffer(ByProtocol, &gEfiPartTypeSystemPartGuid, NULL,
> &NoHandles, &Handles);
> +  if (EFI_ERROR(Status)) {
> +    return Status;
> +  }
> +
> +  //
> +  // Skip BootOptions within FV
> +  //
> +  for (Index = 0; Index < NoHandles; Index++) {
> +    Status = gBS->HandleProtocol (Handles[Index], &gEfiSimpleFileSystemProtocolGuid,
> (VOID **)&FsTemp);
> +    if (!EFI_ERROR (Status)){
> +      *Fs = FsTemp;
> +      break;
> +    }
> +  }
> +  return Status;
> +}
> +
> +/**
> +  Copy a list of capsule images to the active UEFI system partition from bootoption
> list.
> +
> +  @param[in] CapsuleBuffer    An array of pointer to capsule images
> +  @param[in] FileSize         An array of UINTN to capsule images size
> +  @param[in] CapsuleNum       The count of capsule images
> +
> +  @retval EFI_SUCCESS   Capsule images are copied to the active UEFI system partition
> +**/
> +EFI_STATUS
> +CopyCapsuleToActiveEfiPartition(
> +  IN VOID                          **CapsuleBuffer,
> +  IN UINTN                         *FileSize,
> +  IN UINTN                         CapsuleNum
> +  )
> +{
> +  EFI_STATUS                       Status;
> +  CHAR16                           *CapsuleName;
> +  UINTN                            Index;
> +  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL  *Fs;
> +  EFI_FILE_HANDLE                  RootDir;
> +  EFI_FILE_HANDLE                  CapsuleDir;
> +  EFI_FILE_HANDLE                  DestHandle;
> +  UINTN                            DataSize;
> +  UINT64                           OsIndication;
> +
> +  RootDir      = NULL;
> +  CapsuleDir   = NULL;
> +
> +  Status = GetEfiSysPartition(&Fs);
> +  if (EFI_ERROR(Status)) {
> +    Print (L"Can not find active UEFI System Partition\n");
> +    return Status;
> +  }
> +
> +  Status = Fs->OpenVolume(Fs, &RootDir);
> +  if (EFI_ERROR(Status)) {
> +    goto EXIT;
> +  }
> +
> +  Status = RootDir->Open(
> +                      RootDir,
> +                      &CapsuleDir,
> +                      EFI_CAPSULE_FROM_FILE_DIR,
> +                      EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE,
> +                      EFI_FILE_DIRECTORY
> +                      );
> +  if (EFI_ERROR(Status)) {
> +    goto EXIT;
> +  }
> +
> +  //
> +  // Read the input files.
> +  //
> +  for (Index = 0; Index < CapsuleNum; Index++) {
> +    CapsuleName = Argv[CapsuleFirstIndex + Index];
> +    Status = CapsuleDir->Open(
> +                           CapsuleDir,
> +                           &DestHandle,
> +                           CapsuleName,
> +                           EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE |
> EFI_FILE_MODE_CREATE,
> +                           EFI_FILE_ARCHIVE
> +                           );
> +    if (EFI_ERROR(Status)) {
> +      Print(L"CapsuleApp: %s open error - %r\n", CapsuleName, Status);
> +      continue;
> +    }
> +
> +    DataSize = FileSize[Index];
> +    Status = DestHandle->Write(
> +                           DestHandle,
> +                           &DataSize,
> +                           CapsuleBuffer[Index]
> +                           );
> +    DestHandle->Close(DestHandle);
> +    if (EFI_ERROR(Status)) {
> +      Print(L"CapsuleApp: %s write error - %r, FileSize - 0x%x\n", CapsuleName,
> Status, FileSize[Index]);
> +    }
> +  }
> +
> +  Status = gRT->GetVariable (
> +                  L"OsIndications",
> +                  &gEfiGlobalVariableGuid,
> +                  NULL,
> +                  &DataSize,
> +                  (VOID *) &OsIndication
> +                  );
> +
> +  if (EFI_ERROR(Status) || DataSize != sizeof(OsIndication)) {
> +    OsIndication = 0;
> +  }
> +
> +  //
> +  // Set OsIndications Variable EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED bit
> +  //
> +  OsIndication |= EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED;
> +  Status = gRT->SetVariable (
> +                  L"OsIndications",
> +                  &gEfiGlobalVariableGuid,
> +                  EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS |
> +                  EFI_VARIABLE_BOOTSERVICE_ACCESS,
> +                  sizeof(OsIndication),
> +                  (VOID *)&OsIndication
> +                  );
> +
> +
> +EXIT:
> +  if (RootDir != NULL) {
> +    RootDir->Close(RootDir);
> +  }
> +
> +  if (CapsuleDir != NULL) {
> +    CapsuleDir->Close(CapsuleDir);
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  Build Gather list for a list of capsule images.
> +
> +  @param[in]  CapsuleBuffer    An array of pointer to capsule images
> +  @param[in]  FileSize         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                         *FileSize,
> +  IN UINTN                         CapsuleNum,
> +  OUT EFI_CAPSULE_BLOCK_DESCRIPTOR **BlockDescriptors
> +  )
> +{
> +  EFI_STATUS                    Status;
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR  *BlockDescriptors1;
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR  *BlockDescriptors2;
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR  *BlockDescriptorPre;
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR  *BlockDescriptorsHeader;
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR  *TempBlockPtr;
> +  UINT8                         *TempDataPtr;
> +  UINTN                         SizeLeft;
> +  UINTN                         Size;
> +  INT32                         Count;
> +  INT32                         Number;
> +  UINTN                         Index;
> +
> +  TempBlockPtr           = NULL;
> +  BlockDescriptors1      = NULL;
> +  BlockDescriptors2      = NULL;
> +  BlockDescriptorPre     = NULL;
> +  BlockDescriptorsHeader = NULL;
> +
> +  for (Index = 0; Index < CapsuleNum; Index++) {
> +    //
> +    // Allocate memory for the descriptors.
> +    //
> +    if (NumberOfDescriptors == 1) {
> +      Count = 2;
> +    } else {
> +      Count = (INT32)(NumberOfDescriptors + 2) / 2;
> +    }
> +
> +    Size               = Count * sizeof (EFI_CAPSULE_BLOCK_DESCRIPTOR);
> +    BlockDescriptors1  = AllocateRuntimeZeroPool (Size);
> +    if (BlockDescriptors1 == NULL) {
> +      Print (L"CapsuleApp: failed to allocate memory for descriptors\n");
> +      Status = EFI_OUT_OF_RESOURCES;
> +      goto ERREXIT;
> +    } else {
> +      Print (L"CapsuleApp: creating capsule descriptors at 0x%X\n", (UINTN)
> BlockDescriptors1);
> +      Print (L"CapsuleApp: capsule data starts          at 0x%X with size 0x%X\n",
> (UINTN) CapsuleBuffer, FileSize);
> +    }
> +
> +    //
> +    // Record descirptor header
> +    //
> +    if (Index == 0) {
> +      BlockDescriptorsHeader = BlockDescriptors1;
> +    }
> +
> +    if (BlockDescriptorPre != NULL) {
> +      BlockDescriptorPre->Union.ContinuationPointer = (UINTN) BlockDescriptors1;
> +      BlockDescriptorPre->Length = 0;
> +    }
> +
> +    //
> +    // Fill them in
> +    //
> +    TempBlockPtr  = BlockDescriptors1;
> +    TempDataPtr   = CapsuleBuffer[Index];
> +    SizeLeft      = FileSize[Index];
> +    for (Number = 0; (Number < Count - 1) && (SizeLeft != 0); Number++) {
> +      //
> +      // Divide remaining data in half
> +      //
> +      if (NumberOfDescriptors != 1) {
> +        if (SizeLeft == 1) {
> +          Size = 1;
> +        } else {
> +          Size = SizeLeft / 2;
> +        }
> +      } else {
> +        Size = SizeLeft;
> +      }
> +      TempBlockPtr->Union.DataBlock    = (UINTN)TempDataPtr;
> +      TempBlockPtr->Length  = Size;
> +      Print (L"CapsuleApp: capsule block/size              0x%X/0x%X\n", (UINTN)
> TempDataPtr, Size);
> +      SizeLeft -= Size;
> +      TempDataPtr += Size;
> +      TempBlockPtr++;
> +    }
> +
> +    //
> +    // Allocate the second list, point the first block's last entry to point
> +    // to this one, and fill this one in. Worst case is that the previous
> +    // list only had one element that pointed here, so we need at least two
> +    // elements -- one to point to all the data, another to terminate the list.
> +    //
> +    if ((NumberOfDescriptors != 1) && (SizeLeft != 0)) {
> +      Count = (INT32)(NumberOfDescriptors + 2) - Count;
> +      if (Count == 1) {
> +        Count++;
> +      }
> +
> +      Size              = Count * sizeof (EFI_CAPSULE_BLOCK_DESCRIPTOR);
> +      BlockDescriptors2 = AllocateRuntimeZeroPool (Size);
> +      if (BlockDescriptors2 == NULL) {
> +        Print (L"CapsuleApp: failed to allocate memory for descriptors\n");
> +        Status = EFI_OUT_OF_RESOURCES;
> +        goto ERREXIT;
> +      }
> +
> +      //
> +      // Point the first list's last element to point to this second list.
> +      //
> +      TempBlockPtr->Union.ContinuationPointer   = (UINTN) BlockDescriptors2;
> +
> +      TempBlockPtr->Length  = 0;
> +      TempBlockPtr = BlockDescriptors2;
> +      for (Number = 0; Number < Count - 1; Number++) {
> +        //
> +        // If second-to-last one, then dump rest to this element
> +        //
> +        if (Number == (Count - 2)) {
> +          Size = SizeLeft;
> +        } else {
> +          //
> +          // Divide remaining data in half
> +          //
> +          if (SizeLeft == 1) {
> +            Size = 1;
> +          } else {
> +            Size = SizeLeft / 2;
> +          }
> +        }
> +
> +        TempBlockPtr->Union.DataBlock    = (UINTN)TempDataPtr;
> +        TempBlockPtr->Length  = Size;
> +        Print (L"CapsuleApp: capsule block/size              0x%X/0x%X\n", (UINTN)
> TempDataPtr, Size);
> +        SizeLeft -= Size;
> +        TempDataPtr += Size;
> +        TempBlockPtr++;
> +        if (SizeLeft == 0) {
> +          break;
> +        }
> +      }
> +    }
> +
> +    BlockDescriptorPre = TempBlockPtr;
> +    BlockDescriptors1  = NULL;
> +  }
> +
> +  //
> +  // Null-terminate.
> +  //
> +  if (TempBlockPtr != NULL) {
> +    TempBlockPtr->Union.ContinuationPointer    = (UINTN)NULL;
> +    TempBlockPtr->Length  = 0;
> +    *BlockDescriptors = BlockDescriptorsHeader;
> +  }
> +
> +  return EFI_SUCCESS;
> +
> +ERREXIT:
> +  if (BlockDescriptors1 != NULL) {
> +    FreePool(BlockDescriptors1);
> +  }
> +
> +  if (BlockDescriptors2 != NULL) {
> +    FreePool(BlockDescriptors2);
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  Clear the Gather list for a list of capsule images.
> +
> +  @param[in]  BlockDescriptors The block descriptors for the capsule images
> +  @param[in]  CapsuleNum       The count of capsule images
> +**/
> +VOID
> +CleanGatherList(
> +  IN EFI_CAPSULE_BLOCK_DESCRIPTOR   *BlockDescriptors,
> +  IN UINTN                          CapsuleNum
> +  )
> +{
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR   *TempBlockPtr;
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR   *TempBlockPtr1;
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR   *TempBlockPtr2;
> +  UINTN                          Index;
> +
> +  if (BlockDescriptors != NULL) {
> +    TempBlockPtr1 = BlockDescriptors;
> +    while (1){
> +      TempBlockPtr = TempBlockPtr1;
> +      for (Index = 0; Index < CapsuleNum; Index++) {
> +        if (TempBlockPtr[Index].Length == 0) {
> +          break;
> +        }
> +      }
> +
> +      if (TempBlockPtr[Index].Union.ContinuationPointer == (UINTN)NULL) {
> +        break;
> +      }
> +
> +      TempBlockPtr2 = (VOID *) ((UINTN) TempBlockPtr->Union.ContinuationPointer);
> +      FreePool(TempBlockPtr1);
> +      TempBlockPtr1 = TempBlockPtr2;
> +    }
> +  }
> +}
> +
> +/**
> +  Print APP usage.
> +**/
> +VOID
> +PrintUsage (
> +  VOID
> +  )
> +{
> +  Print(L"CapsuleApp:  usage\n");
> +  Print(L"  CapsuleApp [-F] <Capsule...> [-NR]\n");
> +  Print(L"  CapsuleApp -S\n");
> +  Print(L"  CapsuleApp -C\n");
> +  Print(L"  CapsuleApp -P\n");
> +  Print(L"  CapsuleApp -E\n");
> +  Print(L"  CapsuleApp -G <BMP> -O <Capsule>\n");
> +  Print(L"  CapsuleApp -N <Capsule> -O <NestedCapsule>\n");
> +  Print(L"  CapsuleApp -D|-DS <Capsule>\n");
> +  Print(L"Parameter:\n");
> +  Print(L"  -F:  Put capsule file to disk.\n");
> +  Print(L"       No -F means to put capsule file in memory.\n");
> +  Print(L"  -NR: No Reset.\n");
> +  Print(L"  -S:  Dump capsule status.\n");
> +  Print(L"  -C:  Clear capsule status.\n");
> +  Print(L"  -P:  Dump FMP protocol info.\n");
> +  Print(L"  -E:  Dump ESRT table info.\n");
> +  Print(L"  -G:  Input BMP file name\n");
> +  Print(L"  -N:  Append Capsule Header accroding to Windows Firmware Update\n");
> +  Print(L"  -O:  Output Capsule file name\n");
> +  Print(L"  -D:  Dump Capsule\n");
> +  Print(L"  -DS: Dump Capsule with System FMP format\n");
> +}
> +
> +/**
> +  Update Capsule image.
> +
> +  @param[in]  ImageHandle     The image handle.
> +  @param[in]  SystemTable     The system table.
> +
> +  @retval EFI_SUCCESS            Command completed successfully.
> +  @retval EFI_INVALID_PARAMETER  Command usage error.
> +  @retval EFI_NOT_FOUND          The input file can't be found.
> +**/
> +EFI_STATUS
> +EFIAPI
> +UefiMain (
> +  IN EFI_HANDLE        ImageHandle,
> +  IN EFI_SYSTEM_TABLE  *SystemTable
> +  )
> +{
> +  EFI_STATUS                    Status;
> +  UINTN                         FileSize[MAX_CAPSULE_NUM];
> +  VOID                          *CapsuleBuffer[MAX_CAPSULE_NUM];
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR  *BlockDescriptors;
> +  EFI_CAPSULE_HEADER             *CapsuleHeaderArray[MAX_CAPSULE_NUM + 1];
> +  UINT64                         MaxCapsuleSize;
> +  EFI_RESET_TYPE                 ResetType;
> +  BOOLEAN                        NeedReset;
> +  BOOLEAN                        NoReset;
> +  BOOLEAN                        NeedCopyOnDisk;
> +  CHAR16                         *CapsuleName;
> +  UINTN                          CapsuleNum;
> +  UINTN                          Index;
> +
> +  Status = GetArg();
> +  if (EFI_ERROR(Status)) {
> +    PrintUsage();
> +    return Status;
> +  }
> +  if (Argc < 2) {
> +    PrintUsage();
> +    CleanArg();
> +    return EFI_INVALID_PARAMETER;
> +  }
> +  if ((StrCmp(Argv[1], L"-D") == 0) ||
> +      (StrCmp(Argv[1], L"-DS") == 0)) {
> +    Status = DumpCapsule();
> +    CleanArg();
> +    return Status;
> +  }
> +  if (StrCmp(Argv[1], L"-G") == 0) {
> +    Status = CreateBmpFmp();
> +    CleanArg();
> +    return Status;
> +  }
> +  if (StrCmp(Argv[1], L"-N") == 0) {
> +    Status = CreateNestedFmp();
> +    CleanArg();
> +    return Status;
> +  }
> +  if (StrCmp(Argv[1], L"-S") == 0) {
> +    Status = DmpCapsuleStatusVariable();
> +    CleanArg();
> +    return EFI_SUCCESS;
> +  }
> +  if (StrCmp(Argv[1], L"-C") == 0) {
> +    Status = ClearCapsuleStatusVariable();
> +    CleanArg();
> +    return Status;
> +  }
> +  if (StrCmp(Argv[1], L"-P") == 0) {
> +    DumpFmpData();
> +    CleanArg();
> +    return EFI_SUCCESS;
> +  }
> +  if (StrCmp(Argv[1], L"-E") == 0) {
> +    DumpEsrtData();
> +    CleanArg();
> +    return EFI_SUCCESS;
> +  }
> +  if (StrCmp(Argv[1], L"-F") == 0) {
> +    NeedCopyOnDisk = TRUE;
> +    CapsuleFirstIndex = 2;
> +  } else {
> +    NeedCopyOnDisk = FALSE;
> +    CapsuleFirstIndex = 1;
> +  }
> +  if (StrCmp(Argv[Argc - 1], L"-NR") == 0) {
> +    NoReset = TRUE;
> +    CapsuleLastIndex = Argc - 2;
> +  } else {
> +    NoReset = FALSE;
> +    CapsuleLastIndex = Argc - 1;
> +  }
> +  CapsuleNum = CapsuleLastIndex - CapsuleFirstIndex + 1;
> +
> +  if (CapsuleFirstIndex > CapsuleLastIndex) {
> +    Print(L"CapsuleApp: NO capsule image.\n");
> +    CleanArg();
> +    return EFI_UNSUPPORTED;
> +  }
> +  if (CapsuleNum > MAX_CAPSULE_NUM) {
> +    Print(L"CapsuleApp: Too many capsule images.\n");
> +    CleanArg();
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  ZeroMem(&CapsuleBuffer, sizeof(CapsuleBuffer));
> +  ZeroMem(&FileSize, sizeof(FileSize));
> +  BlockDescriptors = NULL;
> +
> +  for (Index = 0; Index < CapsuleNum; Index++) {
> +    CapsuleName = Argv[CapsuleFirstIndex + Index];
> +    Status = ReadFileToBuffer(CapsuleName, &FileSize[Index], &CapsuleBuffer[Index]);
> +    if (EFI_ERROR(Status)) {
> +      Print(L"CapsuleApp: capsule image (%s) is not found.\n", CapsuleName);
> +      goto Done;
> +    }
> +  }
> +
> +  if (NeedCopyOnDisk) {
> +    Status = CopyCapsuleToActiveEfiPartition(CapsuleBuffer, FileSize, CapsuleNum);
> +  } else {
> +    //
> +    // Every capsule use 2 descriptor 1 for data 1 for end
> +    //
> +    Status = BuildGatherList(CapsuleBuffer, FileSize, CapsuleNum, &BlockDescriptors);
> +  }
> +  if (EFI_ERROR(Status)) {
> +    goto Done;
> +  }
> +
> +  //
> +  // Call the runtime service capsule.
> +  //
> +  NeedReset = FALSE;
> +  for (Index = 0; Index < CapsuleNum; Index++) {
> +    CapsuleHeaderArray[Index] = (EFI_CAPSULE_HEADER *) CapsuleBuffer[Index];
> +    if ((CapsuleHeaderArray[Index]->Flags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET) != 0)
> {
> +      NeedReset = TRUE;
> +    }
> +  }
> +  CapsuleHeaderArray[CapsuleNum] = NULL;
> +  if (NoReset) {
> +    NeedReset = FALSE;
> +  }
> +
> +  //
> +  // Inquire platform capability of UpdateCapsule.
> +  //
> +  Status = gRT->QueryCapsuleCapabilities (CapsuleHeaderArray, CapsuleNum,
> &MaxCapsuleSize, &ResetType);
> +  if (EFI_ERROR(Status)) {
> +    Print (L"CapsuleApp: failed to query capsule capability - %r\n", Status);
> +    goto Done;
> +  }
> +
> +  for (Index = 0; Index < CapsuleNum; Index++) {
> +    if (FileSize[Index] > MaxCapsuleSize) {
> +      Print (L"CapsuleApp: capsule is too large to update, %ld is allowed\n",
> MaxCapsuleSize);
> +      Status = EFI_UNSUPPORTED;
> +      goto Done;
> +    }
> +  }
> +
> +  //
> +  // Check whether the input capsule image has the flag of persist across system
> reset.
> +  //
> +  if (NeedReset) {
> +    Status = gRT->UpdateCapsule(CapsuleHeaderArray,CapsuleNum,(UINTN)
> BlockDescriptors);
> +    if (Status != EFI_SUCCESS) {
> +      Print (L"CapsuleApp: failed to update capsule - %r\n", Status);
> +      goto Done;
> +    }
> +    //
> +    // For capsule who has reset flag, after calling UpdateCapsule service,triger a
> +    // system reset to process capsule persist across a system reset.
> +    //
> +    gRT->ResetSystem (ResetType, EFI_SUCCESS, 0, NULL);
> +  } else {
> +    //
> +    // For capsule who has no reset flag, only call UpdateCapsule Service without a
> +    // system reset. The service will process the capsule immediately.
> +    //
> +    Status = gRT->UpdateCapsule (CapsuleHeaderArray,CapsuleNum,(UINTN)
> BlockDescriptors);
> +    if (Status != EFI_SUCCESS) {
> +      Print (L"CapsuleApp: failed to update capsule - %r\n", Status);
> +    }
> +  }
> +
> +  Status = EFI_SUCCESS;
> +
> +Done:
> +  for (Index = 0; Index < CapsuleNum; Index++) {
> +    if (CapsuleBuffer[Index] != NULL) {
> +      FreePool (CapsuleBuffer[Index]);
> +    }
> +  }
> +
> +  CleanGatherList(BlockDescriptors, CapsuleNum);
> +  CleanArg();
> +
> +  return Status;
> +}
> diff --git a/MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf
> b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf
> new file mode 100644
> index 0000000..7ee44fc
> --- /dev/null
> +++ b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf
> @@ -0,0 +1,71 @@
> +##  @file
> +#  A shell application that triggers capsule update process.
> +#
> +# This application can trigger capsule update process. It can also
> +# generate capsule image, or dump capsule variable information.
> +#
> +#  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
> +#  This program and the accompanying materials
> +#  are licensed and made available under the terms and conditions of the BSD License
> +#  which accompanies this distribution.  The full text of the license may be found at
> +#  http://opensource.org/licenses/bsd-license.php
> +#
> +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +#
> +##
> +
> +[Defines]
> +  INF_VERSION                    = 0x00010006
> +  BASE_NAME                      = CapsuleApp
> +  MODULE_UNI_FILE                = CapsuleApp.uni
> +  FILE_GUID                      = 4CEF31DA-8682-4274-9CC4-AEE7516A5E7B
> +  MODULE_TYPE                    = UEFI_APPLICATION
> +  VERSION_STRING                 = 1.0
> +  ENTRY_POINT                    = UefiMain
> +
> +#
> +# The following information is for reference only and not required by the build tools.
> +#
> +#  VALID_ARCHITECTURES           = IA32 X64
> +#
> +
> +[Sources]
> +  CapsuleApp.c
> +  CapsuleDump.c
> +  AppSupport.c
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +
> +[Guids]
> +  gEfiFileInfoGuid
> +  gEfiPartTypeSystemPartGuid
> +  gEfiGlobalVariableGuid
> +  gEfiCapsuleReportGuid
> +  gEfiFmpCapsuleGuid
> +  gWindowsUxCapsuleGuid
> +  gEfiCertTypeRsa2048Sha256Guid
> +  gEfiCertPkcs7Guid
> +  gEfiSystemResourceTableGuid
> +
> +[Protocols]
> +  gEfiLoadedImageProtocolGuid
> +  gEfiSimpleFileSystemProtocolGuid
> +  gEfiGraphicsOutputProtocolGuid
> +  gEfiFirmwareManagementProtocolGuid
> +
> +[LibraryClasses]
> +  BaseLib
> +  UefiApplicationEntryPoint
> +  DebugLib
> +  MemoryAllocationLib
> +  UefiBootServicesTableLib
> +  UefiRuntimeServicesTableLib
> +  UefiLib
> +  PrintLib
> +  EdkiiSystemCapsuleLib
> +
> +[UserExtensions.TianoCore."ExtraFiles"]
> +  CapsuleAppExtra.uni
> diff --git a/MdeModulePkg/Application/CapsuleApp/CapsuleApp.uni
> b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.uni
> new file mode 100644
> index 0000000..54d6e12
> --- /dev/null
> +++ b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.uni
> @@ -0,0 +1,22 @@
> +// /** @file
> +// A shell application that triggers capsule update process.
> +//
> +// This application can trigger capsule update process. It can also
> +// generate capsule image, or dump capsule variable information.
> +//
> +// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
> +//
> +// This program and the accompanying materials
> +// are licensed and made available under the terms and conditions of the BSD License
> +// which accompanies this distribution. The full text of the license may be found at
> +// http://opensource.org/licenses/bsd-license.php
> +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +//
> +// **/
> +
> +
> +#string STR_MODULE_ABSTRACT             #language en-US "A shell application that
> triggers capsule update process."
> +
> +#string STR_MODULE_DESCRIPTION          #language en-US "This application can trigger
> capsule update process. It can also generate capsule image, or dump capsule variable
> information."
> +
> diff --git a/MdeModulePkg/Application/CapsuleApp/CapsuleAppExtra.uni
> b/MdeModulePkg/Application/CapsuleApp/CapsuleAppExtra.uni
> new file mode 100644
> index 0000000..b5a8840
> --- /dev/null
> +++ b/MdeModulePkg/Application/CapsuleApp/CapsuleAppExtra.uni
> @@ -0,0 +1,19 @@
> +// /** @file
> +// CapsuleApp Localized Strings and Content
> +//
> +// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
> +//
> +// This program and the accompanying materials
> +// are licensed and made available under the terms and conditions of the BSD License
> +// which accompanies this distribution. The full text of the license may be found at
> +// http://opensource.org/licenses/bsd-license.php
> +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +//
> +// **/
> +
> +#string STR_PROPERTIES_MODULE_NAME
> +#language en-US
> +"Capsule Application"
> +
> +
> diff --git a/MdeModulePkg/Application/CapsuleApp/CapsuleDump.c
> b/MdeModulePkg/Application/CapsuleApp/CapsuleDump.c
> new file mode 100644
> index 0000000..c56f41f
> --- /dev/null
> +++ b/MdeModulePkg/Application/CapsuleApp/CapsuleDump.c
> @@ -0,0 +1,840 @@
> +/** @file
> +  Dump Capsule image information.
> +
> +  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the BSD License
> +  which accompanies this distribution.  The full text of the license may be found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +
> +**/
> +
> +#include <PiDxe.h>
> +#include <Library/BaseLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/UefiRuntimeServicesTableLib.h>
> +#include <Library/UefiLib.h>
> +#include <Library/PrintLib.h>
> +#include <Library/EdkiiSystemCapsuleLib.h>
> +#include <Protocol/FirmwareManagement.h>
> +#include <Guid/ImageAuthentication.h>
> +#include <Guid/EdkiiSystemFmpCapsule.h>
> +#include <Guid/CapsuleReport.h>
> +#include <Guid/SystemResourceTable.h>
> +#include <Guid/FmpCapsule.h>
> +#include <IndustryStandard/WindowsUxCapsule.h>
> +
> +/**
> +  Read a file.
> +
> +  @param FileName        The file to be read.
> +  @param BufferSize      The file buffer size
> +  @param Buffer          The file buffer
> +
> +  @retval EFI_SUCCESS    Read file successfully
> +  @retval EFI_NOT_FOUND  File not found
> +**/
> +EFI_STATUS
> +ReadFileToBuffer(
> +  IN  CHAR16                               *FileName,
> +  OUT UINTN                                *BufferSize,
> +  OUT VOID                                 **Buffer
> +  );
> +
> +extern UINTN  Argc;
> +extern CHAR16 *Argv[];
> +
> +/**
> +  Dump UX capsule information.
> +
> +  @param CapsuleHeader      The UX capsule header
> +**/
> +VOID
> +DumpUxCapsule(
> +  IN EFI_CAPSULE_HEADER  *CapsuleHeader
> +  )
> +{
> +  EFI_DISPLAY_CAPSULE                           *DisplayCapsule;
> +  DisplayCapsule = (EFI_DISPLAY_CAPSULE *)CapsuleHeader;
> +  Print(L"[UxCapusule]\n");
> +  Print(L"CapsuleHeader:\n");
> +  Print(L"  CapsuleGuid      - %g\n", &DisplayCapsule->CapsuleHeader.CapsuleGuid);
> +  Print(L"  HeaderSize       - 0x%x\n", DisplayCapsule->CapsuleHeader.HeaderSize);
> +  Print(L"  Flags            - 0x%x\n", DisplayCapsule->CapsuleHeader.Flags);
> +  Print(L"  CapsuleImageSize - 0x%x\n", DisplayCapsule-
> >CapsuleHeader.CapsuleImageSize);
> +  Print(L"ImagePayload:\n");
> +  Print(L"  Version          - 0x%x\n", DisplayCapsule->ImagePayload.Version);
> +  Print(L"  Checksum         - 0x%x\n", DisplayCapsule->ImagePayload.Checksum);
> +  Print(L"  ImageType        - 0x%x\n", DisplayCapsule->ImagePayload.ImageType);
> +  Print(L"  Mode             - 0x%x\n", DisplayCapsule->ImagePayload.Mode);
> +  Print(L"  OffsetX          - 0x%x\n", DisplayCapsule->ImagePayload.OffsetX);
> +  Print(L"  OffsetY          - 0x%x\n", DisplayCapsule->ImagePayload.OffsetY);
> +}
> +
> +/**
> +  Dump FMP image authentication information.
> +
> +  @param Image      The FMP capsule image
> +  @param ImageSize  The size of the FMP capsule image in bytes.
> +
> +  @return the size of FMP authentication.
> +**/
> +UINTN
> +DumpImageAuthentication(
> +  IN VOID   *Image,
> +  IN UINTN  ImageSize
> +  )
> +{
> +  EFI_FIRMWARE_IMAGE_AUTHENTICATION             *ImageAuthentication;
> +
> +  ImageAuthentication = Image;
> +  if (CompareGuid(&ImageAuthentication->AuthInfo.CertType, &gEfiCertPkcs7Guid) ||
> +      CompareGuid(&ImageAuthentication->AuthInfo.CertType,
> &gEfiCertTypeRsa2048Sha256Guid)) {
> +    Print(L"[ImageAuthentication]\n");
> +    Print(L"  MonotonicCount   - 0x%lx\n", ImageAuthentication->MonotonicCount);
> +    Print(L"WIN_CERTIFICATE:\n");
> +    Print(L"  dwLength         - 0x%x\n", ImageAuthentication->AuthInfo.Hdr.dwLength);
> +    Print(L"  wRevision        - 0x%x\n", ImageAuthentication-
> >AuthInfo.Hdr.wRevision);
> +    Print(L"  wCertificateType - 0x%x\n", ImageAuthentication-
> >AuthInfo.Hdr.wCertificateType);
> +    Print(L"  CertType         - %g\n", &ImageAuthentication->AuthInfo.CertType);
> +    return sizeof(ImageAuthentication->MonotonicCount) + ImageAuthentication-
> >AuthInfo.Hdr.dwLength;
> +  } else {
> +    return 0;
> +  }
> +}
> +
> +/**
> +  Dump EDKII system FMP capsule.
> +
> +  @param Image      The EDKII system FMP capsule.
> +  @param ImageSize  The size of the EDKII system FMP capsule in bytes.
> +**/
> +VOID
> +DumpEdkiiSystemFmpCapsule(
> +  IN VOID   *Image,
> +  IN UINTN  ImageSize
> +  )
> +{
> +  UINTN                                         ImageOffset;
> +  VOID                                          *BiosImage;
> +  UINTN                                         BiosImageSize;
> +  BOOLEAN                                       Result;
> +  EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR        *TempImageFmpInfo;
> +  EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR        *ImageFmpInfo;
> +  UINTN                                         ImageFmpInfoSize;
> +
> +  //
> +  // We do not know if there is EFI_FIRMWARE_IMAGE_AUTHENTICATION.
> +  // so just *try* to parse it
> +  //
> +  ImageOffset = DumpImageAuthentication(Image, ImageSize);
> +  Image = (UINT8 *)Image + ImageOffset;
> +  ImageSize -= ImageOffset;
> +  Print(L"[Image]\n");
> +  Print(L"  ImageSize   - 0x%x\n", ImageSize);
> +
> +  Result = ExtractConfigImage(Image, ImageSize, &BiosImage, &BiosImageSize);
> +  if (Result) {
> +    Print(L"  ConfigFileSize  - 0x%x\n", BiosImageSize);
> +  }
> +  Result = ExtractDriverFvImage(Image, ImageSize, &BiosImage, &BiosImageSize);
> +  if (Result) {
> +    Print(L"  DriverFvSize    - 0x%x\n", BiosImageSize);
> +  }
> +  Result = ExtractSystemFirmwareImage(Image, ImageSize, &BiosImage, &BiosImageSize);
> +  if (Result) {
> +    Print(L"  BiosImageSize   - 0x%x\n", BiosImageSize);
> +  }
> +  Result = ExtractSystemFirmwareImageFmpInfo(BiosImage, BiosImageSize,
> &TempImageFmpInfo, &ImageFmpInfoSize);
> +  if (Result) {
> +    ImageFmpInfo = AllocateCopyPool(ImageFmpInfoSize, TempImageFmpInfo);
> +    if (ImageFmpInfo != NULL) {
> +      Print(L"[ImageFmpInfo]\n");
> +      Print(L"  Signature                      - 0x%x\n", ImageFmpInfo->Signature);
> +      Print(L"  HeaderLength                   - 0x%x\n", ImageFmpInfo->HeaderLength);
> +      Print(L"  Length                         - 0x%x\n", ImageFmpInfo->Length);
> +      Print(L"  PackageVersion                 - 0x%x\n", ImageFmpInfo-
> >PackageVersion);
> +      Print(L"  PackageVersionNameStringOffset - 0x%x\n", ImageFmpInfo-
> >PackageVersionNameStringOffset);
> +      if (ImageFmpInfo->PackageVersionNameStringOffset != 0) {
> +        Print(L"                                 - %s\n", (UINT8 *)ImageFmpInfo +
> ImageFmpInfo->PackageVersionNameStringOffset);
> +      }
> +      Print(L"  ImageIndex                     - 0x%x\n", ImageFmpInfo->ImageIndex);
> +      Print(L"  ImageTypeId                    - %g\n", &ImageFmpInfo->ImageTypeId);
> +      Print(L"  ImageId                        - 0x%lx\n", ImageFmpInfo->ImageId);
> +      Print(L"  ImageIdNameStringOffset        - 0x%x\n", ImageFmpInfo-
> >ImageIdNameStringOffset);
> +      if (ImageFmpInfo->ImageIdNameStringOffset != 0) {
> +        Print(L"                                 - %s\n", (UINT8 *)ImageFmpInfo +
> ImageFmpInfo->ImageIdNameStringOffset);
> +      }
> +      Print(L"  Version                        - 0x%x\n", ImageFmpInfo->Version);
> +      Print(L"  VersionNameStringOffset        - 0x%x\n", ImageFmpInfo-
> >VersionNameStringOffset);
> +      if (ImageFmpInfo->VersionNameStringOffset != 0) {
> +        Print(L"                                 - %s\n", (UINT8 *)ImageFmpInfo +
> ImageFmpInfo->VersionNameStringOffset);
> +      }
> +      Print(L"  Size                           - 0x%lx\n", ImageFmpInfo->Size);
> +      Print(L"  AttributesSupported            - 0x%lx\n", ImageFmpInfo-
> >AttributesSupported);
> +      Print(L"  AttributesSetting              - 0x%lx\n", ImageFmpInfo-
> >AttributesSetting);
> +      Print(L"  Compatibilities                - 0x%lx\n", ImageFmpInfo-
> >Compatibilities);
> +      Print(L"  LowestSupportedImageVersion    - 0x%x\n", ImageFmpInfo-
> >LowestSupportedImageVersion);
> +      Print(L"  LastAttemptVersion             - 0x%x\n", ImageFmpInfo-
> >LastAttemptVersion);
> +      Print(L"  LastAttemptStatus              - 0x%x\n", ImageFmpInfo-
> >LastAttemptStatus);
> +      Print(L"  HardwareInstance               - 0x%lx\n", ImageFmpInfo-
> >HardwareInstance);
> +      Print(L"  Version                        - 0x%x\n", ImageFmpInfo->Version);
> +      FreePool(ImageFmpInfo);
> +    }
> +  }
> +}
> +
> +/**
> +  Dump a non-nested FMP capsule.
> +
> +  @param  CapsuleHeader  A pointer to CapsuleHeader
> +  @param  IsSystemFmp    If it is a system FMP
> +**/
> +VOID
> +DumpFmpCapsule(
> +  IN EFI_CAPSULE_HEADER  *CapsuleHeader,
> +  IN BOOLEAN             IsSystemFmp
> +  )
> +{
> +  EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER        *FmpCapsuleHeader;
> +  UINT64                                        *ItemOffsetList;
> +  UINTN                                         Index;
> +  UINTN                                         Count;
> +  EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER  *FmpImageHeader;
> +  VOID                                          *Image;
> +
> +  Print(L"[FmpCapusule]\n");
> +  Print(L"CapsuleHeader:\n");
> +  Print(L"  CapsuleGuid      - %g\n", &CapsuleHeader->CapsuleGuid);
> +  Print(L"  HeaderSize       - 0x%x\n", CapsuleHeader->HeaderSize);
> +  Print(L"  Flags            - 0x%x\n", CapsuleHeader->Flags);
> +  Print(L"  CapsuleImageSize - 0x%x\n", CapsuleHeader->CapsuleImageSize);
> +
> +  FmpCapsuleHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *)((UINT8 *)CapsuleHeader
> + CapsuleHeader->HeaderSize);
> +  ItemOffsetList = (UINT64 *)(FmpCapsuleHeader + 1);
> +  Print(L"FmpHeader:\n");
> +  Print(L"  Version             - 0x%x\n", FmpCapsuleHeader->Version);
> +  Print(L"  EmbeddedDriverCount - 0x%x\n", FmpCapsuleHeader->EmbeddedDriverCount);
> +  Print(L"  PayloadItemCount    - 0x%x\n", FmpCapsuleHeader->PayloadItemCount);
> +  Count = FmpCapsuleHeader->EmbeddedDriverCount + FmpCapsuleHeader->PayloadItemCount;
> +  for (Index = 0; Index < Count; Index++) {
> +    Print(L"  Offset[%d]           - 0x%x\n", Index, ItemOffsetList[Index]);
> +  }
> +
> +  for (Index = FmpCapsuleHeader->EmbeddedDriverCount; Index < Count; Index++) {
> +    Print(L"FmpPayload[%d] ImageHeader:\n", Index);
> +    FmpImageHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *)((UINT8
> *)FmpCapsuleHeader + ItemOffsetList[Index]);
> +    Print(L"  Version                - 0x%x\n", FmpImageHeader->Version);
> +    Print(L"  UpdateImageTypeId      - %g\n", &FmpImageHeader->UpdateImageTypeId);
> +    Print(L"  UpdateImageIndex       - 0x%x\n", FmpImageHeader->UpdateImageIndex);
> +    Print(L"  UpdateImageSize        - 0x%x\n", FmpImageHeader->UpdateImageSize);
> +    Print(L"  UpdateVendorCodeSize   - 0x%x\n", FmpImageHeader->UpdateVendorCodeSize);
> +    if (FmpImageHeader->Version >=
> EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {
> +      Print(L"  UpdateHardwareInstance - 0x%lx\n", FmpImageHeader-
> >UpdateHardwareInstance);
> +    }
> +    if (FmpImageHeader->Version >=
> EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {
> +      Image = (UINT8 *)(FmpImageHeader + 1);
> +    }  else {
> +      Image = (UINT8 *)FmpImageHeader +
> OFFSET_OF(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER, UpdateHardwareInstance);
> +    }
> +    if (IsSystemFmp) {
> +      DumpEdkiiSystemFmpCapsule(Image, FmpImageHeader->UpdateImageSize);
> +    }
> +  }
> +}
> +
> +/**
> +  Return if there is a FMP header below capsule header.
> +
> +  @param[in] CapsuleHeader A pointer to EFI_CAPSULE_HEADER
> +
> +  @retval TRUE  There is a FMP header below capsule header.
> +  @retval FALSE There is not a FMP header below capsule header
> +**/
> +BOOLEAN
> +IsNestedFmpCapsule(
> +  IN EFI_CAPSULE_HEADER         *CapsuleHeader
> +  )
> +{
> +  EFI_STATUS                 Status;
> +  EFI_SYSTEM_RESOURCE_TABLE  *Esrt;
> +  EFI_SYSTEM_RESOURCE_ENTRY  *EsrtEntry;
> +  UINTN                      Index;
> +  BOOLEAN                    EsrtGuidFound;
> +  EFI_CAPSULE_HEADER         *NestedCapsuleHeader;
> +  UINTN                      NestedCapsuleSize;
> +
> +  //
> +  // Check ESRT
> +  //
> +  EsrtGuidFound = FALSE;
> +  Status = EfiGetSystemConfigurationTable(&gEfiSystemResourceTableGuid, (VOID
> **)&Esrt);
> +  if (!EFI_ERROR(Status)) {
> +    EsrtEntry = (VOID *)(Esrt + 1);
> +    for (Index = 0; Index < Esrt->FwResourceCount; Index++, EsrtEntry++) {
> +      if (CompareGuid(&EsrtEntry->FwClass, &CapsuleHeader->CapsuleGuid)) {
> +        EsrtGuidFound = TRUE;
> +        break;
> +      }
> +    }
> +  }
> +
> +  if (!EsrtGuidFound) {
> +    return FALSE;
> +  }
> +
> +  //
> +  // Check nested capsule header
> +  // FMP GUID after ESRT one
> +  //
> +  NestedCapsuleHeader = (EFI_CAPSULE_HEADER *)((UINT8 *)CapsuleHeader + CapsuleHeader-
> >HeaderSize);
> +  NestedCapsuleSize = (UINTN)CapsuleHeader + CapsuleHeader->HeaderSize -
> (UINTN)NestedCapsuleHeader;
> +  if (NestedCapsuleSize < sizeof(EFI_CAPSULE_HEADER)) {
> +    return FALSE;
> +  }
> +  if (!CompareGuid(&NestedCapsuleHeader->CapsuleGuid, &gEfiFmpCapsuleGuid)) {
> +    return FALSE;
> +  }
> +  return TRUE;
> +}
> +
> +/**
> +  Dump capsule information
> +
> +  @retval EFI_SUCCESS            The capsule information is dumped.
> +  @retval EFI_UNSUPPORTED        Input parameter is not valid.
> +**/
> +EFI_STATUS
> +DumpCapsule(
> +  VOID
> +  )
> +{
> +  CHAR16                                        *CapsuleName;
> +  VOID                                          *Buffer;
> +  UINTN                                         FileSize;
> +  BOOLEAN                                       IsSystemFmp;
> +  EFI_CAPSULE_HEADER                            *CapsuleHeader;
> +  EFI_STATUS                                    Status;
> +
> +  if (Argc != 3) {
> +    Print(L"CapsuleApp: Invalid Parameter.\n");
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  IsSystemFmp = FALSE;
> +  if (StrCmp(Argv[1], L"-DS") == 0) {
> +    IsSystemFmp = TRUE;
> +  }
> +
> +  CapsuleName = Argv[2];
> +  Status = ReadFileToBuffer(CapsuleName, &FileSize, &Buffer);
> +  if (EFI_ERROR(Status)) {
> +    Print(L"CapsuleApp: Capsule (%s) is not found.\n", CapsuleName);
> +    goto Done;
> +  }
> +
> +  CapsuleHeader = Buffer;
> +  if (CompareGuid(&CapsuleHeader->CapsuleGuid, &gWindowsUxCapsuleGuid)) {
> +    DumpUxCapsule(CapsuleHeader);
> +    Status = EFI_SUCCESS;
> +    goto Done;
> +  }
> +
> +  if (CompareGuid(&CapsuleHeader->CapsuleGuid, &gEfiFmpCapsuleGuid)) {
> +    DumpFmpCapsule(CapsuleHeader, IsSystemFmp);
> +  }
> +  if (IsNestedFmpCapsule(CapsuleHeader)) {
> +    Print(L"[NestedCapusule]\n");
> +    Print(L"CapsuleHeader:\n");
> +    Print(L"  CapsuleGuid      - %g\n", &CapsuleHeader->CapsuleGuid);
> +    Print(L"  HeaderSize       - 0x%x\n", CapsuleHeader->HeaderSize);
> +    Print(L"  Flags            - 0x%x\n", CapsuleHeader->Flags);
> +    Print(L"  CapsuleImageSize - 0x%x\n", CapsuleHeader->CapsuleImageSize);
> +    DumpFmpCapsule((EFI_CAPSULE_HEADER *)((UINTN)CapsuleHeader + CapsuleHeader-
> >HeaderSize), IsSystemFmp);
> +  }
> +
> +Done:
> +  FreePool(Buffer);
> +  return Status;
> +}
> +
> +/**
> +  Dump capsule status variable.
> +
> +  @retval EFI_SUCCESS            The capsule status variable is dumped.
> +  @retval EFI_UNSUPPORTED        Input parameter is not valid.
> +**/
> +EFI_STATUS
> +DmpCapsuleStatusVariable(
> +  VOID
> +  )
> +{
> +  EFI_STATUS                          Status;
> +  UINT32                              Index;
> +  CHAR16                              CapsuleVarName[20];
> +  CHAR16                              *TempVarName;
> +  EFI_CAPSULE_RESULT_VARIABLE_HEADER  *CapsuleResult;
> +  EFI_CAPSULE_RESULT_VARIABLE_FMP     *CapsuleResultFmp;
> +  UINTN                               CapsuleFileNameSize;
> +  CHAR16                              CapsuleIndexData[12];
> +  CHAR16                              *CapsuleIndex;
> +
> +  Status = GetVariable2(
> +             L"CapsuleMax",
> +             &gEfiCapsuleReportGuid,
> +             (VOID **)&CapsuleIndex,
> +             NULL
> +             );
> +  if (!EFI_ERROR(Status)) {
> +    CopyMem(CapsuleIndexData, CapsuleIndex, 11 * sizeof(CHAR16));
> +    CapsuleIndexData[11] = 0;
> +    Print(L"CapsuleMax - %s\n", CapsuleIndexData);
> +    FreePool(CapsuleIndex);
> +  }
> +  Status = GetVariable2(
> +             L"CapsuleLast",
> +             &gEfiCapsuleReportGuid,
> +             (VOID **)&CapsuleIndex,
> +             NULL
> +             );
> +  if (!EFI_ERROR(Status)) {
> +    CopyMem(CapsuleIndexData, CapsuleIndex, 11 * sizeof(CHAR16));
> +    CapsuleIndexData[11] = 0;
> +    Print(L"CapsuleLast - %s\n", CapsuleIndexData);
> +    FreePool(CapsuleIndex);
> +  }
> +
> +
> +  StrCpyS (CapsuleVarName, sizeof(CapsuleVarName)/sizeof(CapsuleVarName[0]),
> L"Capsule");
> +  TempVarName = CapsuleVarName + StrLen (CapsuleVarName);
> +  Index = 0;
> +
> +  while (TRUE) {
> +    UnicodeSPrint (TempVarName, 5 * sizeof(CHAR16), L"%04x", Index);
> +
> +    Status = GetVariable2 (
> +               CapsuleVarName,
> +               &gEfiCapsuleReportGuid,
> +               (VOID **) &CapsuleResult,
> +               NULL
> +               );
> +    if (Status == EFI_NOT_FOUND) {
> +      break;
> +    } else if (EFI_ERROR(Status)) {
> +      continue;
> +    }
> +
> +    //
> +    // display capsule process status
> +    //
> +    if (CapsuleResult->VariableTotalSize >=
> sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER)) {
> +      Print (L"CapsuleName: %s\n", CapsuleVarName);
> +      Print (L"  Capsule Guid: %g\n", &CapsuleResult->CapsuleGuid);
> +      Print (L"  Capsule ProcessedTime: %t\n", &CapsuleResult->CapsuleProcessed);
> +      Print (L"  Capsule Status: %r\n", CapsuleResult->CapsuleStatus);
> +    }
> +
> +    if (CompareGuid(&CapsuleResult->CapsuleGuid, &gEfiFmpCapsuleGuid)) {
> +      if (CapsuleResult->VariableTotalSize >=
> sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER) + sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP)) {
> +        CapsuleResultFmp = (EFI_CAPSULE_RESULT_VARIABLE_FMP *)(CapsuleResult + 1);
> +        Print(L"  Capsule FMP Version: 0x%x\n", CapsuleResultFmp->Version);
> +        Print(L"  Capsule FMP PayloadIndex: 0x%x\n", CapsuleResultFmp->PayloadIndex);
> +        Print(L"  Capsule FMP UpdateImageIndex: 0x%x\n", CapsuleResultFmp-
> >UpdateImageIndex);
> +        Print(L"  Capsule FMP UpdateImageTypeId: %g\n", &CapsuleResultFmp-
> >UpdateImageTypeId);
> +        if (CapsuleResult->VariableTotalSize >
> sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER) + sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP)) {
> +          Print(L"  Capsule FMP CapsuleFileName: %s\n", (CapsuleResultFmp + 1));
> +          CapsuleFileNameSize = StrSize((CHAR16 *)(CapsuleResultFmp + 1));
> +          if (CapsuleResult->VariableTotalSize >
> sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER) + sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP) +
> CapsuleFileNameSize) {
> +            Print(L"  Capsule FMP CapsuleTarget: %s\n", (UINT8 *)(CapsuleResultFmp +
> 1) + CapsuleFileNameSize);
> +          }
> +        }
> +      }
> +    }
> +
> +    FreePool(CapsuleResult);
> +
> +    Index++;
> +    if (Index > 0xFFFF) {
> +      break;
> +    }
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +CHAR8 *mFwTypeString[] = {
> +  "Unknown",
> +  "SystemFirmware",
> +  "DeviceFirmware",
> +  "UefiDriver",
> +};
> +
> +CHAR8 *mLastAttemptStatusString[] = {
> +  "Success",
> +  "Error: Unsuccessful",
> +  "Error: Insufficient Resources",
> +  "Error: Incorrect Version",
> +  "Error: Invalid Format",
> +  "Error: Auth Error",
> +  "Error: Power Event AC",
> +  "Error: Power Event Battery",
> +};
> +
> +/**
> +  Convert FwType to a string.
> +
> +  @param FwType  FwType in ESRT
> +
> +  @return a string for FwType.
> +**/
> +CHAR8 *
> +FwTypeToString(
> +  IN UINT32 FwType
> +  )
> +{
> +  if (FwType < sizeof(mFwTypeString) / sizeof(mFwTypeString[0])) {
> +    return mFwTypeString[FwType];
> +  } else {
> +    return "Invalid";
> +  }
> +}
> +
> +/**
> +  Convert LastAttemptStatus to a string.
> +
> +  @param LastAttemptStatus  LastAttemptStatus in FMP or ESRT
> +
> +  @return a string for LastAttemptStatus.
> +**/
> +CHAR8 *
> +LastAttemptStatusToString(
> +  IN UINT32 LastAttemptStatus
> +  )
> +{
> +  if (LastAttemptStatus < sizeof(mLastAttemptStatusString) /
> sizeof(mLastAttemptStatusString[0])) {
> +    return mLastAttemptStatusString[LastAttemptStatus];
> +  } else {
> +    return "Error: Unknown";
> +  }
> +}
> +
> +/**
> +  Dump ESRT entry.
> +
> +  @param EsrtEntry  ESRT entry
> +**/
> +VOID
> +DumpEsrtEntry(
> +  IN EFI_SYSTEM_RESOURCE_ENTRY  *EsrtEntry
> +  )
> +{
> +  Print(L"  FwClass                  - %g\n", &EsrtEntry->FwClass);
> +  Print(L"  FwType                   - 0x%x (%a)\n", EsrtEntry->FwType,
> FwTypeToString(EsrtEntry->FwType));
> +  Print(L"  FwVersion                - 0x%x\n", EsrtEntry->FwVersion);
> +  Print(L"  LowestSupportedFwVersion - 0x%x\n", EsrtEntry->LowestSupportedFwVersion);
> +  Print(L"  CapsuleFlags             - 0x%x\n", EsrtEntry->CapsuleFlags);
> +  Print(L"    PERSIST_ACROSS_RESET   - 0x%x\n", EsrtEntry->CapsuleFlags &
> CAPSULE_FLAGS_PERSIST_ACROSS_RESET);
> +  Print(L"    POPULATE_SYSTEM_TABLE  - 0x%x\n", EsrtEntry->CapsuleFlags &
> CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE);
> +  Print(L"    INITIATE_RESET         - 0x%x\n", EsrtEntry->CapsuleFlags &
> CAPSULE_FLAGS_INITIATE_RESET);
> +  Print(L"  LastAttemptVersion       - 0x%x\n", EsrtEntry->LastAttemptVersion);
> +  Print(L"  LastAttemptStatus        - 0x%x (%a)\n", EsrtEntry->LastAttemptStatus,
> LastAttemptStatusToString(EsrtEntry->LastAttemptStatus));
> +}
> +
> +/**
> +  Dump ESRT table.
> +
> +  @param Esrt  ESRT table
> +**/
> +VOID
> +DumpEsrt(
> +  IN EFI_SYSTEM_RESOURCE_TABLE  *Esrt
> +  )
> +{
> +  UINTN                      Index;
> +  EFI_SYSTEM_RESOURCE_ENTRY  *EsrtEntry;
> +
> +  Print(L"EFI_SYSTEM_RESOURCE_TABLE:\n");
> +  Print(L"FwResourceCount    - 0x%x\n", Esrt->FwResourceCount);
> +  Print(L"FwResourceCountMax - 0x%x\n", Esrt->FwResourceCountMax);
> +  Print(L"FwResourceVersion  - 0x%lx\n", Esrt->FwResourceVersion);
> +
> +  EsrtEntry = (VOID *)(Esrt + 1);
> +  for (Index = 0; Index < Esrt->FwResourceCount; Index++) {
> +    Print(L"EFI_SYSTEM_RESOURCE_ENTRY (%d):\n", Index);
> +    DumpEsrtEntry(EsrtEntry);
> +    EsrtEntry++;
> +  }
> +}
> +
> +/**
> +  Dump ESRT info.
> +**/
> +VOID
> +DumpEsrtData (
> +  VOID
> +  )
> +{
> +  EFI_STATUS                 Status;
> +  EFI_SYSTEM_RESOURCE_TABLE  *Esrt;
> +
> +  Print(L"##############\n");
> +  Print(L"# ESRT TABLE #\n");
> +  Print(L"##############\n");
> +
> +  Status = EfiGetSystemConfigurationTable (&gEfiSystemResourceTableGuid, (VOID
> **)&Esrt);
> +  if (EFI_ERROR(Status)) {
> +    Print(L"ESRT - %r\n", Status);
> +    return;
> +  }
> +  DumpEsrt(Esrt);
> +  Print(L"\n");
> +}
> +
> +/**
> +  Dump FMP information.
> +
> +  @param ImageInfoSize       The size of ImageInfo, in bytes.
> +  @param ImageInfo           A pointer to EFI_FIRMWARE_IMAGE_DESCRIPTOR.
> +  @param DescriptorVersion   The version of EFI_FIRMWARE_IMAGE_DESCRIPTOR.
> +  @param DescriptorCount     The count of EFI_FIRMWARE_IMAGE_DESCRIPTOR.
> +  @param DescriptorSize      The size of an individual EFI_FIRMWARE_IMAGE_DESCRIPTOR,
> in bytes.
> +  @param PackageVersion      The version of package.
> +  @param PackageVersionName  The version name of package.
> +**/
> +VOID
> +DumpFmpImageInfo(
> +  IN UINTN                           ImageInfoSize,
> +  IN EFI_FIRMWARE_IMAGE_DESCRIPTOR   *ImageInfo,
> +  IN UINT32                          DescriptorVersion,
> +  IN UINT8                           DescriptorCount,
> +  IN UINTN                           DescriptorSize,
> +  IN UINT32                          PackageVersion,
> +  IN CHAR16                          *PackageVersionName
> +  )
> +{
> +  EFI_FIRMWARE_IMAGE_DESCRIPTOR                 *CurrentImageInfo;
> +  UINTN                                         Index;
> +
> +  Print(L"  DescriptorVersion  - 0x%x\n", DescriptorVersion);
> +  Print(L"  DescriptorCount    - 0x%x\n", DescriptorCount);
> +  Print(L"  DescriptorSize     - 0x%x\n", DescriptorSize);
> +  Print(L"  PackageVersion     - 0x%x\n", PackageVersion);
> +  Print(L"  PackageVersionName - \"%s\"\n", PackageVersionName);
> +  CurrentImageInfo = ImageInfo;
> +  for (Index = 0; Index < DescriptorCount; Index++) {
> +    Print(L"  ImageDescriptor (%d)\n", Index);
> +    Print(L"    ImageIndex                  - 0x%x\n", CurrentImageInfo->ImageIndex);
> +    Print(L"    ImageTypeId                 - %g\n", &CurrentImageInfo->ImageTypeId);
> +    Print(L"    ImageId                     - 0x%lx\n", CurrentImageInfo->ImageId);
> +    Print(L"    ImageIdName                 - \"%s\"\n", CurrentImageInfo-
> >ImageIdName);
> +    Print(L"    Version                     - 0x%x\n", CurrentImageInfo->Version);
> +    Print(L"    VersionName                 - \"%s\"\n", CurrentImageInfo-
> >VersionName);
> +    Print(L"    Size                        - 0x%x\n", CurrentImageInfo->Size);
> +    Print(L"    AttributesSupported         - 0x%lx\n", CurrentImageInfo-
> >AttributesSupported);
> +    Print(L"      IMAGE_UPDATABLE           - 0x%lx\n", CurrentImageInfo-
> >AttributesSupported & IMAGE_ATTRIBUTE_IMAGE_UPDATABLE);
> +    Print(L"      RESET_REQUIRED            - 0x%lx\n", CurrentImageInfo-
> >AttributesSupported & IMAGE_ATTRIBUTE_RESET_REQUIRED);
> +    Print(L"      AUTHENTICATION_REQUIRED   - 0x%lx\n", CurrentImageInfo-
> >AttributesSupported & IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);
> +    Print(L"      IN_USE                    - 0x%lx\n", CurrentImageInfo-
> >AttributesSupported & IMAGE_ATTRIBUTE_IN_USE);
> +    Print(L"      UEFI_IMAGE                - 0x%lx\n", CurrentImageInfo-
> >AttributesSupported & IMAGE_ATTRIBUTE_UEFI_IMAGE);
> +    Print(L"    AttributesSetting           - 0x%lx\n", CurrentImageInfo-
> >AttributesSetting);
> +    Print(L"      IMAGE_UPDATABLE           - 0x%lx\n", CurrentImageInfo-
> >AttributesSetting & IMAGE_ATTRIBUTE_IMAGE_UPDATABLE);
> +    Print(L"      RESET_REQUIRED            - 0x%lx\n", CurrentImageInfo-
> >AttributesSetting & IMAGE_ATTRIBUTE_RESET_REQUIRED);
> +    Print(L"      AUTHENTICATION_REQUIRED   - 0x%lx\n", CurrentImageInfo-
> >AttributesSetting & IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);
> +    Print(L"      IN_USE                    - 0x%lx\n", CurrentImageInfo-
> >AttributesSetting & IMAGE_ATTRIBUTE_IN_USE);
> +    Print(L"      UEFI_IMAGE                - 0x%lx\n", CurrentImageInfo-
> >AttributesSetting & IMAGE_ATTRIBUTE_UEFI_IMAGE);
> +    Print(L"    Compatibilities             - 0x%lx\n", CurrentImageInfo-
> >Compatibilities);
> +    Print(L"      COMPATIB_CHECK_SUPPORTED  - 0x%lx\n", CurrentImageInfo-
> >Compatibilities & IMAGE_COMPATIBILITY_CHECK_SUPPORTED);
> +    if (DescriptorVersion > 1) {
> +      Print(L"    LowestSupportedImageVersion - 0x%x\n", CurrentImageInfo-
> >LowestSupportedImageVersion);
> +      if (DescriptorVersion > 2) {
> +        Print(L"    LastAttemptVersion          - 0x%x\n", CurrentImageInfo-
> >LastAttemptVersion);
> +        Print(L"    LastAttemptStatus           - 0x%x (%a)\n", CurrentImageInfo-
> >LastAttemptStatus, LastAttemptStatusToString(CurrentImageInfo->LastAttemptStatus));
> +        Print(L"    HardwareInstance            - 0x%lx\n", CurrentImageInfo-
> >HardwareInstance);
> +      }
> +    }
> +    //
> +    // Use DescriptorSize to move ImageInfo Pointer to stay compatible with different
> ImageInfo version
> +    //
> +    CurrentImageInfo = (EFI_FIRMWARE_IMAGE_DESCRIPTOR *)((UINT8 *)CurrentImageInfo +
> DescriptorSize);
> +  }
> +}
> +
> +/**
> +  Dump FMP package information.
> +
> +  @param PackageVersion             The version of package.
> +  @param PackageVersionName         The version name of package.
> +  @param PackageVersionNameMaxLen   The maximum length of PackageVersionName.
> +  @param AttributesSupported        Package attributes that are supported by this
> device.
> +  @param AttributesSetting          Package attributes.
> +**/
> +VOID
> +DumpFmpPackageInfo(
> +  IN UINT32                           PackageVersion,
> +  IN CHAR16                           *PackageVersionName,
> +  IN UINT32                           PackageVersionNameMaxLen,
> +  IN UINT64                           AttributesSupported,
> +  IN UINT64                           AttributesSetting
> +  )
> +{
> +  Print(L"  PackageVersion              - 0x%x\n", PackageVersion);
> +  Print(L"  PackageVersionName          - \"%s\"\n", PackageVersionName);
> +  Print(L"  PackageVersionNameMaxLen    - 0x%x\n", PackageVersionNameMaxLen);
> +  Print(L"  AttributesSupported         - 0x%lx\n", AttributesSupported);
> +  Print(L"    IMAGE_UPDATABLE           - 0x%lx\n", AttributesSupported &
> IMAGE_ATTRIBUTE_IMAGE_UPDATABLE);
> +  Print(L"    RESET_REQUIRED            - 0x%lx\n", AttributesSupported &
> IMAGE_ATTRIBUTE_RESET_REQUIRED);
> +  Print(L"    AUTHENTICATION_REQUIRED   - 0x%lx\n", AttributesSupported &
> IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);
> +  Print(L"  AttributesSetting           - 0x%lx\n", AttributesSetting);
> +  Print(L"    IMAGE_UPDATABLE           - 0x%lx\n", AttributesSetting &
> IMAGE_ATTRIBUTE_IMAGE_UPDATABLE);
> +  Print(L"    RESET_REQUIRED            - 0x%lx\n", AttributesSetting &
> IMAGE_ATTRIBUTE_RESET_REQUIRED);
> +  Print(L"    AUTHENTICATION_REQUIRED   - 0x%lx\n", AttributesSetting &
> IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);
> +}
> +
> +/**
> +  Dump FMP protocol info.
> +**/
> +VOID
> +DumpFmpData (
> +  VOID
> +  )
> +{
> +  EFI_STATUS                                    Status;
> +  EFI_FIRMWARE_MANAGEMENT_PROTOCOL              *Fmp;
> +  EFI_HANDLE                                    *HandleBuffer;
> +  UINTN                                         NumberOfHandles;
> +  UINTN                                         Index;
> +  EFI_FIRMWARE_IMAGE_DESCRIPTOR                 *FmpImageInfoBuf;
> +  UINTN                                         ImageInfoSize;
> +  UINT32                                        FmpImageInfoDescriptorVer;
> +  UINT8                                         FmpImageInfoCount;
> +  UINTN                                         DescriptorSize;
> +  UINT32                                        PackageVersion;
> +  CHAR16                                        *PackageVersionName;
> +  UINT32                                        PackageVersionNameMaxLen;
> +  UINT64                                        AttributesSupported;
> +  UINT64                                        AttributesSetting;
> +
> +  Print(L"############\n");
> +  Print(L"# FMP DATA #\n");
> +  Print(L"############\n");
> +  Status = gBS->LocateHandleBuffer (
> +                  ByProtocol,
> +                  &gEfiFirmwareManagementProtocolGuid,
> +                  NULL,
> +                  &NumberOfHandles,
> +                  &HandleBuffer
> +                  );
> +  if (EFI_ERROR(Status)) {
> +    Print(L"FMP protocol - %r\n", EFI_NOT_FOUND);
> +    return;
> +  }
> +
> +  for (Index = 0; Index < NumberOfHandles; Index++) {
> +    Status = gBS->HandleProtocol(
> +                    HandleBuffer[Index],
> +                    &gEfiFirmwareManagementProtocolGuid,
> +                    (VOID **)&Fmp
> +                    );
> +    if (EFI_ERROR(Status)) {
> +      continue;
> +    }
> +
> +    ImageInfoSize = 0;
> +    Status = Fmp->GetImageInfo (
> +                    Fmp,
> +                    &ImageInfoSize,
> +                    NULL,
> +                    NULL,
> +                    NULL,
> +                    NULL,
> +                    NULL,
> +                    NULL
> +                    );
> +    if (Status != EFI_BUFFER_TOO_SMALL) {
> +      continue;
> +    }
> +
> +    FmpImageInfoBuf = NULL;
> +    FmpImageInfoBuf = AllocateZeroPool (ImageInfoSize);
> +    if (FmpImageInfoBuf == NULL) {
> +      Status = EFI_OUT_OF_RESOURCES;
> +      goto EXIT;
> +    }
> +
> +    PackageVersionName = NULL;
> +    Status = Fmp->GetImageInfo (
> +                    Fmp,
> +                    &ImageInfoSize,               // ImageInfoSize
> +                    FmpImageInfoBuf,              // ImageInfo
> +                    &FmpImageInfoDescriptorVer,   // DescriptorVersion
> +                    &FmpImageInfoCount,           // DescriptorCount
> +                    &DescriptorSize,              // DescriptorSize
> +                    &PackageVersion,              // PackageVersion
> +                    &PackageVersionName           // PackageVersionName
> +                    );
> +
> +    //
> +    // If FMP GetInformation interface failed, skip this resource
> +    //
> +    if (EFI_ERROR(Status)) {
> +      Print(L"FMP (%d) ImageInfo - %r\n", Index, Status);
> +      FreePool(FmpImageInfoBuf);
> +      continue;
> +    }
> +
> +    Print(L"FMP (%d) ImageInfo:\n", Index);
> +    DumpFmpImageInfo(
> +      ImageInfoSize,               // ImageInfoSize
> +      FmpImageInfoBuf,             // ImageInfo
> +      FmpImageInfoDescriptorVer,   // DescriptorVersion
> +      FmpImageInfoCount,           // DescriptorCount
> +      DescriptorSize,              // DescriptorSize
> +      PackageVersion,              // PackageVersion
> +      PackageVersionName           // PackageVersionName
> +      );
> +
> +    if (PackageVersionName != NULL) {
> +      FreePool(PackageVersionName);
> +    }
> +    FreePool(FmpImageInfoBuf);
> +
> +    //
> +    // Get package info
> +    //
> +    PackageVersionName = NULL;
> +    Status = Fmp->GetPackageInfo (
> +                    Fmp,
> +                    &PackageVersion,              // PackageVersion
> +                    &PackageVersionName,          // PackageVersionName
> +                    &PackageVersionNameMaxLen,    // PackageVersionNameMaxLen
> +                    &AttributesSupported,         // AttributesSupported
> +                    &AttributesSetting            // AttributesSetting
> +                    );
> +    if (EFI_ERROR(Status)) {
> +      Print(L"FMP (%d) PackageInfo - %r\n", Index, Status);
> +    } else {
> +      Print(L"FMP (%d) ImageInfo:\n", Index);
> +      DumpFmpPackageInfo(
> +        PackageVersion,              // PackageVersion
> +        PackageVersionName,          // PackageVersionName
> +        PackageVersionNameMaxLen,    // PackageVersionNameMaxLen
> +        AttributesSupported,         // AttributesSupported
> +        AttributesSetting            // AttributesSetting
> +        );
> +
> +      if (PackageVersionName != NULL) {
> +        FreePool(PackageVersionName);
> +      }
> +    }
> +  }
> +  Print(L"\n");
> +
> +EXIT:
> +  FreePool(HandleBuffer);
> +}
> --
> 2.7.4.windows.1
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>
https://lists.01.org/mailman/listinfo/edk2-devel

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

* Re: [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application.
  2016-10-11  8:28                     ` Ni, Ruiyu
@ 2016-10-11  8:46                       ` Yao, Jiewen
  2016-10-11 14:44                       ` Yao, Jiewen
  1 sibling, 0 replies; 83+ messages in thread
From: Yao, Jiewen @ 2016-10-11  8:46 UTC (permalink / raw)
  To: Ni, Ruiyu, Carsey, Jaben, Rothman, Michael A, Kinney, Michael D,
	'edk2-devel@lists.01.org'
  Cc: Tian, Feng, Zhang, Chao B, Gao, Liming, Zeng, Star

Yes, I think that is a very good idea.

Shell spec defines EFI_SHELL_PROTOCOL, EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL, EFI_SHELL_PARAMETERS_PROTOCOL.
These should be treated as industry stand and we can move these 3 to MdePkg.

SHELL_ENVIRONMENT_2_PROTOCOL and SHELL_INTERFACE_PROTOCOL should be still in ShellPkg, since it is not standard.

Thank you
Yao Jiewen

From: Ni, Ruiyu
Sent: Tuesday, October 11, 2016 4:28 PM
To: Carsey, Jaben <jaben.carsey@intel.com>; Rothman, Michael A <michael.a.rothman@intel.com>; Yao, Jiewen <jiewen.yao@intel.com>; Kinney, Michael D <michael.d.kinney@intel.com>; 'edk2-devel@lists.01.org' <edk2-devel@lists.01.org>
Cc: Tian, Feng <feng.tian@intel.com>; Zhang, Chao B <chao.b.zhang@intel.com>; Gao, Liming <liming.gao@intel.com>; Zeng, Star <star.zeng@intel.com>
Subject: RE: [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application.

Jaben,
The reason I propose to move the Shell protocol definitions to MdePkg is that all applications that wants to use the ARGV can use the ShellParameter protocol, without depending on ShellPkg.

Thanks/Ray

From: Ni, Ruiyu
Sent: Tuesday, October 11, 2016 4:08 PM
To: Carsey, Jaben <jaben.carsey@intel.com<mailto:jaben.carsey@intel.com>>; Rothman, Michael A <michael.a.rothman@intel.com<mailto:michael.a.rothman@intel.com>>; Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>; edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>
Cc: Tian, Feng <feng.tian@intel.com<mailto:feng.tian@intel.com>>; Zhang, Chao B <chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com>>; Gao, Liming <liming.gao@intel.com<mailto:liming.gao@intel.com>>; Zeng, Star <star.zeng@intel.com<mailto:star.zeng@intel.com>>
Subject: RE: [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application.

Jaben,
How about moving the contents in ShellPkg\Include\Protocol\ to MdePkg\Include\Protocol\?
All industry standard protocols are defined in MdePkg, except the Shell related protocols.

Thanks/Ray

From: Carsey, Jaben
Sent: Tuesday, October 4, 2016 4:38 AM
To: Rothman, Michael A <michael.a.rothman@intel.com<mailto:michael.a.rothman@intel.com>>; Ni, Ruiyu <ruiyu.ni@intel.com<mailto:ruiyu.ni@intel.com>>; Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>; edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>
Cc: Tian, Feng <feng.tian@intel.com<mailto:feng.tian@intel.com>>; Zhang, Chao B <chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com>>; Gao, Liming <liming.gao@intel.com<mailto:liming.gao@intel.com>>; Zeng, Star <star.zeng@intel.com<mailto:star.zeng@intel.com>>; Carsey, Jaben <jaben.carsey@intel.com<mailto:jaben.carsey@intel.com>>
Subject: RE: [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application.

I don’t think that is what I meant.  It’s a string and a length, not a structure.

I mean clarify the following:

1)      Is the name of the binary itself in the LoadOptions string as the first option or not there at all?

2)      Then clarify that all Parameters are space delimited.

From: Rothman, Michael A
Sent: Monday, October 03, 2016 11:36 AM
To: Carsey, Jaben <jaben.carsey@intel.com<mailto:jaben.carsey@intel.com>>; Ni, Ruiyu <ruiyu.ni@intel.com<mailto:ruiyu.ni@intel.com>>; Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>; edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>
Cc: Tian, Feng <feng.tian@intel.com<mailto:feng.tian@intel.com>>; Zhang, Chao B <chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com>>; Gao, Liming <liming.gao@intel.com<mailto:liming.gao@intel.com>>; Zeng, Star <star.zeng@intel.com<mailto:star.zeng@intel.com>>; Rothman, Michael A <michael.a.rothman@intel.com<mailto:michael.a.rothman@intel.com>>
Subject: RE: [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application.
Importance: High

You mean update the LoadOptions reference to refer to the EFI_LOAD_OPTION structure? Because that’s in essence what it means.

Thanks,
Mike Rothman
(迈克 罗斯曼 / माइकल रोथ्मेन् / Михаил Ротман / משה רוטמן)
רועה עיקרי של חתולים

From: Carsey, Jaben
Sent: Friday, September 30, 2016 8:31 AM
To: Ni, Ruiyu <ruiyu.ni@intel.com<mailto:ruiyu.ni@intel.com>>; Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>; edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>; Rothman, Michael A <michael.a.rothman@intel.com<mailto:michael.a.rothman@intel.com>>
Cc: Tian, Feng <feng.tian@intel.com<mailto:feng.tian@intel.com>>; Zhang, Chao B <chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com>>; Gao, Liming <liming.gao@intel.com<mailto:liming.gao@intel.com>>; Zeng, Star <star.zeng@intel.com<mailto:star.zeng@intel.com>>; Carsey, Jaben <jaben.carsey@intel.com<mailto:jaben.carsey@intel.com>>
Subject: RE: [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application.

Mike Rothman,

Can we get LoadOptions and LoadOptionsSize clarified in the UEFI Spec?  This seems like a simple clarification and I would argue its needed.  The UEFI Shell is not the only producer of this protocol.  BDS launches things (like the UEFI Shell itself) and the shell already consumes it for itself (and it works).  I think it just needs clarification so people can depend on the current implementation not changing.

-Jaben

From: Ni, Ruiyu
Sent: Thursday, September 29, 2016 9:13 PM
To: Carsey, Jaben <jaben.carsey@intel.com<mailto:jaben.carsey@intel.com>>; Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>; edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>
Cc: Tian, Feng <feng.tian@intel.com<mailto:feng.tian@intel.com>>; Zhang, Chao B <chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com>>; Gao, Liming <liming.gao@intel.com<mailto:liming.gao@intel.com>>; Zeng, Star <star.zeng@intel.com<mailto:star.zeng@intel.com>>
Subject: RE: [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application.
Importance: High

Supposing user inputs “CapsuleApp.efi Parameter1 Parameter2”.
There is no spec to define what the LoadOption should equal to.
If there is another UEFI Shell implementation, it could interpret the command line then sets only “Parameter1 Parameter2” into LoadOption, or sets “CapsuleApp.efi\tParameter1\tParameter2” to LoadOption, or sets “[Shell]\tCapsuleApp.efi\tParameter1\tParameter2” to LoadOption.
Because it“produces” such LoadOption, it knows how to “consume”/parse it to get the ARGVs.

So I suggest we put the CapsuleApp in ShellPkg and let it use the ShellParameter protocol.

Regards,
Ray

From: Carsey, Jaben
Sent: Friday, September 30, 2016 3:11 AM
To: Ni, Ruiyu <ruiyu.ni@intel.com<mailto:ruiyu.ni@intel.com>>; Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>; edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>
Cc: Tian, Feng <feng.tian@intel.com<mailto:feng.tian@intel.com>>; Zhang, Chao B <chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com>>; Gao, Liming <liming.gao@intel.com<mailto:liming.gao@intel.com>>; Zeng, Star <star.zeng@intel.com<mailto:star.zeng@intel.com>>; Carsey, Jaben <jaben.carsey@intel.com<mailto:jaben.carsey@intel.com>>
Subject: RE: [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application.

I am confused.

Why is LoadOption and LoadOptionSize not working?  This is specified as part of UEFI Spec (Note: Not UEFI Shell Spec) as a standard way to pass parameters to UEFI appliations.  I think this should work (although it is more work than just examining argc/argv).

-Jaben

From: Ni, Ruiyu
Sent: Wednesday, September 28, 2016 11:40 PM
To: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>; edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>
Cc: Tian, Feng <feng.tian@intel.com<mailto:feng.tian@intel.com>>; Zhang, Chao B <chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com>>; Gao, Liming <liming.gao@intel.com<mailto:liming.gao@intel.com>>; Zeng, Star <star.zeng@intel.com<mailto:star.zeng@intel.com>>; Carsey, Jaben <jaben.carsey@intel.com<mailto:jaben.carsey@intel.com>>
Subject: RE: [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application.
Importance: High

Jiewen,
The way CapsuleApp extracts the ARGV assumes UEFI Shell encodes the parameters using a certain way. But the parameter encoding way is not described in the Shell spec.
Maybe we can put the CapsuleApp in ShellPkg, then let it directly use ShellParameter protocol to get the ARGV.

Copying Jaben.

Regards,
Ray

From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of Yao, Jiewen
Sent: Thursday, September 29, 2016 10:37 AM
To: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>; edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>
Cc: Tian, Feng <feng.tian@intel.com<mailto:feng.tian@intel.com>>; Zhang, Chao B <chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com>>; Gao, Liming <liming.gao@intel.com<mailto:liming.gao@intel.com>>; Zeng, Star <star.zeng@intel.com<mailto:star.zeng@intel.com>>
Subject: Re: [edk2] [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application.

Right. CapsuleOnDisk is not supported in BIOS yet.
I will remove it in CapsuleApp.

CapsuleApp just works as an agent to pass capsule to CapsuleDxeRuntime driver.
So it is checked by CapsuleDxeRuntime, not CapsuleApp.

Thank you
Yao Jiewen

From: Kinney, Michael D
Sent: Thursday, September 29, 2016 9:06 AM
To: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>; Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>
Cc: Tian, Feng <feng.tian@intel.com<mailto:feng.tian@intel.com>>; Zeng, Star <star.zeng@intel.com<mailto:star.zeng@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: [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application.

Jiewen,

Does the capsule on disk feature provided by this app work?

I tried it with the QuarkPlatformPkg capsule and I can get
The app to copy the capsule to an EFI System Partition, but
The logic after that point looks incomplete.

Also, if I clear the Persist and Reset flags on the capsule,
the immediate processing of the capsule does not work.

Is there any FW code that will look for capsules on disk?

If there are incomplete features in CapsuleApp, then I think
we should remove them.

Mike

> -----Original Message-----
> From: Yao, Jiewen
> Sent: Tuesday, September 20, 2016 11:45 PM
> To: edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org%3cmailto:edk2-devel@lists.01.org>>
> Cc: Tian, Feng <feng.tian@intel.com<mailto:feng.tian@intel.com<mailto:feng.tian@intel.com%3cmailto:feng.tian@intel.com>>>; Zeng, Star <star.zeng@intel.com<mailto:star.zeng@intel.com<mailto:star.zeng@intel.com%3cmailto:star.zeng@intel.com>>>; Kinney, Michael
> D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com%3cmailto:michael.d.kinney@intel.com>>>; Gao, Liming <liming.gao@intel.com<mailto:liming.gao@intel.com<mailto:liming.gao@intel.com%3cmailto:liming.gao@intel.com>>>; Zhang, Chao B
> <chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com%3cmailto:chao.b.zhang@intel.com>>>
> Subject: [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application.
>
> This CapsuleApp can help perform capsule update in UEFI shell environment.
> It can also dump capsule information, capsule status variable, ESRT and FMP.
>
> Cc: Feng Tian <feng.tian@intel.com<mailto:feng.tian@intel.com<mailto:feng.tian@intel.com%3cmailto:feng.tian@intel.com>>>
> Cc: Star Zeng <star.zeng@intel.com<mailto:star.zeng@intel.com<mailto:star.zeng@intel.com%3cmailto:star.zeng@intel.com>>>
> Cc: Michael D Kinney <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com%3cmailto:michael.d.kinney@intel.com>>>
> Cc: Liming Gao <liming.gao@intel.com<mailto:liming.gao@intel.com<mailto:liming.gao@intel.com%3cmailto:liming.gao@intel.com>>>
> Cc: Chao Zhang <chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com%3cmailto:chao.b.zhang@intel.com>>>
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Jiewen Yao <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com<mailto:jiewen.yao@intel.com%3cmailto:jiewen.yao@intel.com>>>
> ---
>  MdeModulePkg/Application/CapsuleApp/AppSupport.c        |  480 +++++++++
>  MdeModulePkg/Application/CapsuleApp/CapsuleApp.c        | 1047 ++++++++++++++++++++
>  MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf      |   71 ++
>  MdeModulePkg/Application/CapsuleApp/CapsuleApp.uni      |   22 +
>  MdeModulePkg/Application/CapsuleApp/CapsuleAppExtra.uni |   19 +
>  MdeModulePkg/Application/CapsuleApp/CapsuleDump.c       |  840 ++++++++++++++++
>  6 files changed, 2479 insertions(+)
>
> diff --git a/MdeModulePkg/Application/CapsuleApp/AppSupport.c
> b/MdeModulePkg/Application/CapsuleApp/AppSupport.c
> new file mode 100644
> index 0000000..365067d
> --- /dev/null
> +++ b/MdeModulePkg/Application/CapsuleApp/AppSupport.c
> @@ -0,0 +1,480 @@
> +/** @file
> +  A shell application that triggers capsule update process.
> +
> +  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the BSD License
> +  which accompanies this distribution.  The full text of the license may be found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +
> +**/
> +
> +#include <Uefi.h>
> +#include <Library/BaseLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/UefiRuntimeServicesTableLib.h>
> +#include <Library/UefiLib.h>
> +#include <Library/PrintLib.h>
> +#include <Protocol/LoadedImage.h>
> +#include <Protocol/SimpleFileSystem.h>
> +#include <Guid/FileInfo.h>
> +#include <Guid/Gpt.h>
> +
> +#define MAX_ARG_NUM     11
> +
> +UINTN  Argc = 0;
> +CHAR16 *Argv[MAX_ARG_NUM];
> +CHAR16 *ArgBuffer;
> +
> +/**
> +
> +  This function parse application ARG.
> +
> +  @return Status
> +**/
> +EFI_STATUS
> +GetArg (
> +  VOID
> +  )
> +{
> +  UINT8                         *Data;
> +  UINTN                         DataSize;
> +  CHAR16                        *Index;
> +  CHAR16                        *End;
> +  CHAR16                        *DIndex;
> +  EFI_STATUS                    Status;
> +  EFI_LOADED_IMAGE_PROTOCOL     *LoadedImage;
> +
> +  Status = gBS->HandleProtocol (
> +                  gImageHandle,
> +                  &gEfiLoadedImageProtocolGuid,
> +                  (VOID**)&LoadedImage
> +                  );
> +  if (EFI_ERROR(Status)) {
> +    return Status;
> +  }
> +
> +  Data = LoadedImage->LoadOptions;
> +  DataSize = LoadedImage->LoadOptionsSize;
> +
> +  End = (CHAR16*)(UINTN)(Data + DataSize);
> +  Status = gBS->AllocatePool (EfiBootServicesData, DataSize, (VOID **)&ArgBuffer);
> +  ASSERT_EFI_ERROR (Status);
> +  DIndex = ArgBuffer;
> +  Argv[Argc++] = ArgBuffer;
> +  for (Index = (CHAR16*)Data; Index < End; ) {
> +    if (*Index == L' ') {
> +      *DIndex = L'\0';
> +      if (Argc >= MAX_ARG_NUM) {
> +        return EFI_UNSUPPORTED;
> +      }
> +      Argv[Argc++] = (++ DIndex);
> +      while(*Index == L' ') {
> +        Index ++;
> +      }
> +    }
> +    (*(DIndex ++)) = (*(Index ++));
> +  }
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Clear APP ARG.
> +**/
> +VOID
> +CleanArg (
> +  VOID
> +  )
> +{
> +  FreePool (Argv[0]);
> +}
> +
> +/**
> +  Return File System Volume containing this shell application.
> +
> +  @return File System Volume containing this shell application.
> +**/
> +EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *
> +GetMyVol (
> +  VOID
> +  )
> +{
> +  EFI_STATUS                        Status;
> +  EFI_LOADED_IMAGE_PROTOCOL         *LoadedImage;
> +  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Vol;
> +
> +  Status = gBS->HandleProtocol (
> +                  gImageHandle,
> +                  &gEfiLoadedImageProtocolGuid,
> +                  (VOID **)&LoadedImage
> +                  );
> +  ASSERT_EFI_ERROR (Status);
> +
> +  Status = gBS->HandleProtocol (
> +                  LoadedImage->DeviceHandle,
> +                  &gEfiSimpleFileSystemProtocolGuid,
> +                  (VOID **)&Vol
> +                  );
> +  if (!EFI_ERROR (Status)) {
> +    return Vol;
> +  }
> +
> +  return NULL;
> +}
> +
> +/**
> +  Read a file from this volume.
> +
> +  @param Vol             File System Volume
> +  @param FileName        The file to be read.
> +  @param BufferSize      The file buffer size
> +  @param Buffer          The file buffer
> +
> +  @retval EFI_SUCCESS    Read file successfully
> +  @retval EFI_NOT_FOUND  File not found
> +**/
> +EFI_STATUS
> +ReadFileFromVol (
> +  IN  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Vol,
> +  IN  CHAR16                            *FileName,
> +  OUT UINTN                             *BufferSize,
> +  OUT VOID                              **Buffer
> +  )
> +{
> +  EFI_STATUS                        Status;
> +  EFI_FILE_HANDLE                   RootDir;
> +  EFI_FILE_HANDLE                   Handle;
> +  UINTN                             FileInfoSize;
> +  EFI_FILE_INFO                     *FileInfo;
> +  UINTN                             TempBufferSize;
> +  VOID                              *TempBuffer;
> +
> +  //
> +  // Open the root directory
> +  //
> +  Status = Vol->OpenVolume (Vol, &RootDir);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  //
> +  // Open the file
> +  //
> +  Status = RootDir->Open (
> +                      RootDir,
> +                      &Handle,
> +                      FileName,
> +                      EFI_FILE_MODE_READ,
> +                      0
> +                      );
> +  if (EFI_ERROR (Status)) {
> +    RootDir->Close (RootDir);
> +    return Status;
> +  }
> +
> +  RootDir->Close (RootDir);
> +
> +  //
> +  // Get the file information
> +  //
> +  FileInfoSize = sizeof(EFI_FILE_INFO) + 1024;
> +
> +  FileInfo = AllocateZeroPool (FileInfoSize);
> +  if (FileInfo == NULL) {
> +    Handle->Close (Handle);
> +    return Status;
> +  }
> +
> +  Status = Handle->GetInfo (
> +                     Handle,
> +                     &gEfiFileInfoGuid,
> +                     &FileInfoSize,
> +                     FileInfo
> +                     );
> +  if (EFI_ERROR (Status)) {
> +    Handle->Close (Handle);
> +    gBS->FreePool (FileInfo);
> +    return Status;
> +  }
> +
> +  //
> +  // Allocate buffer for the file data. The last CHAR16 is for L'\0'
> +  //
> +  TempBufferSize = (UINTN) FileInfo->FileSize + sizeof(CHAR16);
> +  TempBuffer = AllocateZeroPool (TempBufferSize);
> +  if (TempBuffer == NULL) {
> +    Handle->Close (Handle);
> +    gBS->FreePool (FileInfo);
> +    return Status;
> +  }
> +
> +  gBS->FreePool (FileInfo);
> +
> +  //
> +  // Read the file data to the buffer
> +  //
> +  Status = Handle->Read (
> +                     Handle,
> +                     &TempBufferSize,
> +                     TempBuffer
> +                     );
> +  if (EFI_ERROR (Status)) {
> +    Handle->Close (Handle);
> +    gBS->FreePool (TempBuffer);
> +    return Status;
> +  }
> +
> +  Handle->Close (Handle);
> +
> +  *BufferSize = TempBufferSize;
> +  *Buffer     = TempBuffer;
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Read a file.
> +  If ScanFs is FLASE, it will use this Vol as default Fs.
> +  If ScanFs is TRUE, it will scan all FS and check the file.
> +    If there is only one file match the name, it will be read.
> +    If there is more than one file match the name, it will return Error.
> +
> +  @param ThisVol         File System Volume
> +  @param FileName        The file to be read.
> +  @param BufferSize      The file buffer size
> +  @param Buffer          The file buffer
> +  @param ScanFs          Need Scan all FS
> +
> +  @retval EFI_SUCCESS    Read file successfully
> +  @retval EFI_NOT_FOUND  File not found
> +  @retval EFI_NO_MAPPING There is duplicated files found
> +**/
> +EFI_STATUS
> +ReadFileToBufferEx (
> +  IN OUT EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   **ThisVol,
> +  IN  CHAR16                               *FileName,
> +  OUT UINTN                                *BufferSize,
> +  OUT VOID                                 **Buffer,
> +  IN  BOOLEAN                              ScanFs
> +  )
> +{
> +  EFI_STATUS                        Status;
> +  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Vol;
> +  UINTN                             TempBufferSize;
> +  VOID                              *TempBuffer;
> +  UINTN                             NoHandles;
> +  EFI_HANDLE                        *HandleBuffer;
> +  UINTN                             Index;
> +
> +  //
> +  // Check parameters
> +  //
> +  if ((FileName == NULL) || (Buffer == NULL) || (ThisVol == NULL)) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  //
> +  // not scan fs
> +  //
> +  if (!ScanFs) {
> +    if (*ThisVol == NULL) {
> +      *ThisVol = GetMyVol ();
> +      if (*ThisVol == NULL) {
> +        return EFI_INVALID_PARAMETER;
> +      }
> +    }
> +    //
> +    // Read file directly from Vol
> +    //
> +    return ReadFileFromVol (*ThisVol, FileName, BufferSize, Buffer);
> +  }
> +
> +  //
> +  // need scan fs
> +  //
> +
> +  //
> +  // Get all Vol handle
> +  //
> +  Status = gBS->LocateHandleBuffer (
> +                   ByProtocol,
> +                   &gEfiSimpleFileSystemProtocolGuid,
> +                   NULL,
> +                   &NoHandles,
> +                   &HandleBuffer
> +                   );
> +  if (EFI_ERROR (Status) && (NoHandles == 0)) {
> +    return EFI_NOT_FOUND;
> +  }
> +
> +  //
> +  // Walk through each Vol
> +  //
> +  *ThisVol = NULL;
> +  *BufferSize = 0;
> +  *Buffer     = NULL;
> +  for (Index = 0; Index < NoHandles; Index++) {
> +    Status = gBS->HandleProtocol (
> +                    HandleBuffer[Index],
> +                    &gEfiSimpleFileSystemProtocolGuid,
> +                    (VOID **)&Vol
> +                    );
> +    if (EFI_ERROR(Status)) {
> +      continue;
> +    }
> +
> +    Status = ReadFileFromVol (Vol, FileName, &TempBufferSize, &TempBuffer);
> +    if (!EFI_ERROR (Status)) {
> +      //
> +      // Read file OK, check duplication
> +      //
> +      if (*ThisVol != NULL) {
> +        //
> +        // Find the duplicated file
> +        //
> +        gBS->FreePool (TempBuffer);
> +        gBS->FreePool (*Buffer);
> +        Print (L"Duplicated FileName found!\n");
> +        return EFI_NO_MAPPING;
> +      } else {
> +        //
> +        // Record value
> +        //
> +        *ThisVol = Vol;
> +        *BufferSize = TempBufferSize;
> +        *Buffer     = TempBuffer;
> +      }
> +    }
> +  }
> +
> +  //
> +  // Scan Fs done
> +  //
> +  if (*ThisVol == NULL) {
> +    return EFI_NOT_FOUND;
> +  }
> +
> +  //
> +  // Done
> +  //
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Read a file.
> +
> +  @param FileName        The file to be read.
> +  @param BufferSize      The file buffer size
> +  @param Buffer          The file buffer
> +
> +  @retval EFI_SUCCESS    Read file successfully
> +  @retval EFI_NOT_FOUND  File not found
> +**/
> +EFI_STATUS
> +ReadFileToBuffer (
> +  IN  CHAR16                               *FileName,
> +  OUT UINTN                                *BufferSize,
> +  OUT VOID                                 **Buffer
> +  )
> +{
> +  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Vol;
> +  Vol = NULL;
> +  return ReadFileToBufferEx(&Vol, FileName, BufferSize, Buffer, FALSE);
> +}
> +
> +/**
> +  Write a file.
> +
> +  @param FileName        The file to be written.
> +  @param BufferSize      The file buffer size
> +  @param Buffer          The file buffer
> +
> +  @retval EFI_SUCCESS    Write file successfully
> +**/
> +EFI_STATUS
> +WriteFileFromBuffer(
> +  IN  CHAR16                               *FileName,
> +  IN  UINTN                                BufferSize,
> +  IN  VOID                                 *Buffer
> +  )
> +{
> +  EFI_STATUS                        Status;
> +  EFI_FILE_HANDLE                   RootDir;
> +  EFI_FILE_HANDLE                   Handle;
> +  UINTN                             TempBufferSize;
> +  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Vol;
> +
> +  Vol = GetMyVol();
> +
> +  //
> +  // Open the root directory
> +  //
> +  Status = Vol->OpenVolume (Vol, &RootDir);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  //
> +  // Open the file
> +  //
> +  Status = RootDir->Open (
> +                      RootDir,
> +                      &Handle,
> +                      FileName,
> +                      EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE| EFI_FILE_MODE_CREATE,
> +                      0
> +                      );
> +  if (EFI_ERROR (Status)) {
> +    RootDir->Close (RootDir);
> +    return Status;
> +  }
> +
> +  //
> +  // Delete file
> +  //
> +  Status = Handle->Delete(Handle);
> +  if (EFI_ERROR(Status)) {
> +    return Status;
> +  }
> +
> +  //
> +  // Open the file again
> +  //
> +  Status = RootDir->Open (
> +                      RootDir,
> +                      &Handle,
> +                      FileName,
> +                      EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE| EFI_FILE_MODE_CREATE,
> +                      0
> +                      );
> +  if (EFI_ERROR (Status)) {
> +    RootDir->Close (RootDir);
> +    return Status;
> +  }
> +
> +  RootDir->Close (RootDir);
> +
> +  //
> +  // Write the file data from the buffer
> +  //
> +  TempBufferSize = BufferSize;
> +  Status = Handle->Write (
> +                     Handle,
> +                     &TempBufferSize,
> +                     Buffer
> +                     );
> +  if (EFI_ERROR (Status)) {
> +    Handle->Close (Handle);
> +    return Status;
> +  }
> +
> +  Handle->Close (Handle);
> +
> +  return EFI_SUCCESS;
> +}
> +
> diff --git a/MdeModulePkg/Application/CapsuleApp/CapsuleApp.c
> b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.c
> new file mode 100644
> index 0000000..0a28557
> --- /dev/null
> +++ b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.c
> @@ -0,0 +1,1047 @@
> +/** @file
> +  A shell application that triggers capsule update process.
> +
> +  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the BSD License
> +  which accompanies this distribution.  The full text of the license may be found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +
> +**/
> +
> +#include <Uefi.h>
> +#include <Library/BaseLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/UefiRuntimeServicesTableLib.h>
> +#include <Library/UefiLib.h>
> +#include <Library/PrintLib.h>
> +#include <Protocol/LoadedImage.h>
> +#include <Protocol/SimpleFileSystem.h>
> +#include <Protocol/GraphicsOutput.h>
> +#include <Guid/FileInfo.h>
> +#include <Guid/Gpt.h>
> +#include <Guid/GlobalVariable.h>
> +#include <Guid/CapsuleReport.h>
> +#include <Guid/SystemResourceTable.h>
> +#include <Guid/FmpCapsule.h>
> +#include <IndustryStandard/WindowsUxCapsule.h>
> +
> +#define CAPSULE_HEADER_SIZE  0x20
> +
> +#define NESTED_CAPSULE_HEADER_SIZE  SIZE_4KB
> +#define SYSTEM_FIRMWARE_FLAG 0x50000
> +#define DEVICE_FIRMWARE_FLAG 0x78010
> +
> +#define EFI_CAPSULE_FROM_FILE_DIR                           L"\\EFI\\UpdateCapsule\\<file:///\\EFI\UpdateCapsule\><file:///\\EFI\UpdateCapsule\%3cfile:\EFI\UpdateCapsule\%3e>"
> +#define EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED  0x0000000000000004
> +
> +#define MAJOR_VERSION   1
> +#define MINOR_VERSION   0
> +
> +#define MAX_ARG_NUM     11
> +#define MAX_CAPSULE_NUM (MAX_ARG_NUM - 1)
> +
> +extern UINTN  Argc;
> +extern CHAR16 *Argv[];
> +
> +//
> +// Define how many block descriptors we want to test with.
> +//
> +UINTN  NumberOfDescriptors = 1;
> +UINTN  CapsuleFirstIndex;
> +UINTN  CapsuleLastIndex;
> +
> +/**
> +  Dump capsule information
> +
> +  @retval EFI_SUCCESS            The capsule information is dumped.
> +  @retval EFI_UNSUPPORTED        Input parameter is not valid.
> +**/
> +EFI_STATUS
> +DumpCapsule(
> +  VOID
> +  );
> +
> +/**
> +  Dump capsule status variable.
> +
> +  @retval EFI_SUCCESS            The capsule status variable is dumped.
> +  @retval EFI_UNSUPPORTED        Input parameter is not valid.
> +**/
> +EFI_STATUS
> +DmpCapsuleStatusVariable(
> +  VOID
> +  );
> +
> +/**
> +  Dump FMP protocol info.
> +**/
> +VOID
> +DumpFmpData(
> +  VOID
> +  );
> +
> +/**
> +  Dump ESRT info.
> +**/
> +VOID
> +DumpEsrtData(
> +  VOID
> +  );
> +
> +/**
> +  Read a file.
> +
> +  @param FileName        The file to be read.
> +  @param BufferSize      The file buffer size
> +  @param Buffer          The file buffer
> +
> +  @retval EFI_SUCCESS    Read file successfully
> +  @retval EFI_NOT_FOUND  File not found
> +**/
> +EFI_STATUS
> +ReadFileToBuffer(
> +  IN  CHAR16                               *FileName,
> +  OUT UINTN                                *BufferSize,
> +  OUT VOID                                 **Buffer
> +  );
> +
> +/**
> +  Write a file.
> +
> +  @param FileName        The file to be written.
> +  @param BufferSize      The file buffer size
> +  @param Buffer          The file buffer
> +
> +  @retval EFI_SUCCESS    Write file successfully
> +**/
> +EFI_STATUS
> +WriteFileFromBuffer(
> +  IN  CHAR16                               *FileName,
> +  IN  UINTN                                BufferSize,
> +  IN  VOID                                 *Buffer
> +  );
> +
> +/**
> +
> +  This function parse application ARG.
> +
> +  @return Status
> +**/
> +EFI_STATUS
> +GetArg (
> +  VOID
> +  );
> +
> +/**
> +  Clear APP ARG.
> +**/
> +VOID
> +CleanArg (
> +  VOID
> +  );
> +
> +/**
> +  Create UX capsule.
> +
> +  @retval EFI_SUCCESS            The capsule header is appended.
> +  @retval EFI_UNSUPPORTED        Input parameter is not valid.
> +  @retval EFI_OUT_OF_RESOURCES   No enough resource to create UX capsule.
> +**/
> +EFI_STATUS
> +CreateBmpFmp(
> +  VOID
> +  )
> +{
> +  CHAR16                                        *OutputCapsuleName;
> +  VOID                                          *BmpBuffer;
> +  UINTN                                         FileSize;
> +  CHAR16                                        *BmpName;
> +  UINT8                                         *FullCapsuleBuffer;
> +  UINTN                                         FullCapsuleBufferSize;
> +  EFI_DISPLAY_CAPSULE                           *DisplayCapsule;
> +  EFI_STATUS                                    Status;
> +  EFI_GRAPHICS_OUTPUT_PROTOCOL                  *Gop;
> +
> +  Status = gBS->LocateProtocol(&gEfiGraphicsOutputProtocolGuid, NULL, (VOID **)&Gop);
> +  if (EFI_ERROR(Status)) {
> +    Print(L"CapsuleApp: NO GOP is found.\n");
> +    return EFI_UNSUPPORTED;
> +  }
> +  Print(L"Current GOP: Mode - %d, ", Gop->Mode->Mode);
> +  Print(L"HorizontalResolution - %d, ", Gop->Mode->Info->HorizontalResolution);
> +  Print(L"VerticalResolution - %d\n", Gop->Mode->Info->VerticalResolution);
> +  // HorizontalResolution >= BMP_IMAGE_HEADER.PixelWidth
> +  // VerticalResolution   >= BMP_IMAGE_HEADER.PixelHeight
> +
> +  if (Argc != 5) {
> +    Print(L"CapsuleApp: Invalid Parameter.\n");
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  if (StrCmp(Argv[3], L"-O") != 0) {
> +    Print(L"CapsuleApp: NO output capsule name.\n");
> +    return EFI_UNSUPPORTED;
> +  }
> +  OutputCapsuleName = Argv[4];
> +
> +  BmpBuffer = NULL;
> +  FileSize = 0;
> +  FullCapsuleBuffer = NULL;
> +
> +  BmpName = Argv[2];
> +  Status = ReadFileToBuffer(BmpName, &FileSize, &BmpBuffer);
> +  if (EFI_ERROR(Status)) {
> +    Print(L"CapsuleApp: BMP image (%s) is not found.\n", BmpName);
> +    goto Done;
> +  }
> +
> +  FullCapsuleBufferSize = sizeof(EFI_DISPLAY_CAPSULE) + FileSize;
> +  FullCapsuleBuffer = AllocatePool(FullCapsuleBufferSize);
> +  if (FullCapsuleBuffer == NULL) {
> +    Print(L"CapsuleApp: Capsule Buffer size (0x%x) too big.\n",
> FullCapsuleBufferSize);
> +    Status = EFI_OUT_OF_RESOURCES;
> +    goto Done;
> +  }
> +
> +  DisplayCapsule = (EFI_DISPLAY_CAPSULE *)FullCapsuleBuffer;
> +  CopyGuid(&DisplayCapsule->CapsuleHeader.CapsuleGuid, &gWindowsUxCapsuleGuid);
> +  DisplayCapsule->CapsuleHeader.HeaderSize = sizeof(DisplayCapsule->CapsuleHeader);
> +  DisplayCapsule->CapsuleHeader.Flags = CAPSULE_FLAGS_PERSIST_ACROSS_RESET;
> +  DisplayCapsule->CapsuleHeader.CapsuleImageSize = (UINT32)FullCapsuleBufferSize;
> +
> +  DisplayCapsule->ImagePayload.Version = 1;
> +  DisplayCapsule->ImagePayload.Checksum = 0;
> +  DisplayCapsule->ImagePayload.ImageType = 0; // BMP
> +  DisplayCapsule->ImagePayload.Reserved = 0;
> +  DisplayCapsule->ImagePayload.Mode = Gop->Mode->Mode;
> +  DisplayCapsule->ImagePayload.OffsetX = 0;
> +  DisplayCapsule->ImagePayload.OffsetY = 0;
> +
> +  CopyMem((DisplayCapsule + 1), BmpBuffer, FileSize);
> +
> +  DisplayCapsule->ImagePayload.Checksum = CalculateCheckSum8(FullCapsuleBuffer,
> FullCapsuleBufferSize);
> +
> +  Status = WriteFileFromBuffer(OutputCapsuleName, FullCapsuleBufferSize,
> FullCapsuleBuffer);
> +  Print(L"CapsuleApp: Write %s %r\n", OutputCapsuleName, Status);
> +
> +Done:
> +  if (BmpBuffer != NULL) {
> +    FreePool(BmpBuffer);
> +  }
> +
> +  if (FullCapsuleBuffer != NULL) {
> +    FreePool(FullCapsuleBuffer);
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  Get ImageTypeId in the FMP capsule header.
> +
> +  @param CapsuleHeader  The FMP capsule image header.
> +
> +  @return ImageTypeId
> +**/
> +EFI_GUID *
> +GetCapsuleImageTypeId(
> +  IN EFI_CAPSULE_HEADER                            *CapsuleHeader
> +  )
> +{
> +  EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER       *FmpCapsuleHeader;
> +  UINT64                                       *ItemOffsetList;
> +  EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader;
> +
> +  FmpCapsuleHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *)((UINT8 *)CapsuleHeader
> + CapsuleHeader->HeaderSize);
> +  ItemOffsetList = (UINT64 *)(FmpCapsuleHeader + 1);
> +  if (FmpCapsuleHeader->PayloadItemCount == 0) {
> +    return NULL;
> +  }
> +  ImageHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *)((UINT8
> *)FmpCapsuleHeader + ItemOffsetList[FmpCapsuleHeader->EmbeddedDriverCount]);
> +  return &ImageHeader->UpdateImageTypeId;
> +}
> +
> +/**
> +  Get ESRT FwType according to ImageTypeId
> +
> +  @param  ImageTypeId   ImageTypeId of an FMP capsule.
> +
> +  @return ESRT FwType
> +**/
> +UINT32
> +GetEsrtFwType(
> +  IN  EFI_GUID                                      *ImageTypeId
> +  )
> +{
> +  EFI_STATUS                 Status;
> +  EFI_SYSTEM_RESOURCE_TABLE  *Esrt;
> +  EFI_SYSTEM_RESOURCE_ENTRY  *EsrtEntry;
> +  UINTN                      Index;
> +
> +  //
> +  // Check ESRT
> +  //
> +  Status = EfiGetSystemConfigurationTable(&gEfiSystemResourceTableGuid, (VOID
> **)&Esrt);
> +  if (!EFI_ERROR(Status)) {
> +    EsrtEntry = (VOID *)(Esrt + 1);
> +    for (Index = 0; Index < Esrt->FwResourceCount; Index++, EsrtEntry++) {
> +      if (CompareGuid(&EsrtEntry->FwClass, ImageTypeId)) {
> +        return EsrtEntry->FwType;
> +      }
> +    }
> +  }
> +
> +  return ESRT_FW_TYPE_UNKNOWN;
> +}
> +
> +/**
> +  Append a capsule header on top of current image.
> +  This function follows Windows UEFI Firmware Update Platform document.
> +
> +  @retval EFI_SUCCESS            The capsule header is appended.
> +  @retval EFI_UNSUPPORTED        Input parameter is not valid.
> +  @retval EFI_OUT_OF_RESOURCES   No enough resource to append capsule header.
> +**/
> +EFI_STATUS
> +CreateNestedFmp(
> +  VOID
> +  )
> +{
> +  CHAR16                                        *OutputCapsuleName;
> +  VOID                                          *CapsuleBuffer;
> +  UINTN                                         FileSize;
> +  CHAR16                                        *CapsuleName;
> +  UINT8                                         *FullCapsuleBuffer;
> +  UINTN                                         FullCapsuleBufferSize;
> +  EFI_CAPSULE_HEADER                            *NestedCapsuleHeader;
> +  EFI_GUID                                      *ImageTypeId;
> +  UINT32                                        FwType;
> +  EFI_STATUS                                    Status;
> +
> +  if (Argc != 5) {
> +    Print(L"CapsuleApp: Invalid Parameter.\n");
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  if (StrCmp(Argv[3], L"-O") != 0) {
> +    Print(L"CapsuleApp: NO output capsule name.\n");
> +    return EFI_UNSUPPORTED;
> +  }
> +  OutputCapsuleName = Argv[4];
> +
> +  CapsuleBuffer = NULL;
> +  FileSize = 0;
> +  FullCapsuleBuffer = NULL;
> +
> +  CapsuleName = Argv[2];
> +  Status = ReadFileToBuffer(CapsuleName, &FileSize, &CapsuleBuffer);
> +  if (EFI_ERROR(Status)) {
> +    Print(L"CapsuleApp: Capsule image (%s) is not found.\n", CapsuleName);
> +    goto Done;
> +  }
> +
> +  ImageTypeId = GetCapsuleImageTypeId(CapsuleBuffer);
> +  if (ImageTypeId == NULL) {
> +    Print(L"CapsuleApp: Capsule ImageTypeId is not found.\n");
> +    goto Done;
> +  }
> +  FwType = GetEsrtFwType(ImageTypeId);
> +  if ((FwType != ESRT_FW_TYPE_SYSTEMFIRMWARE) && (FwType !=
> ESRT_FW_TYPE_DEVICEFIRMWARE)) {
> +    Print(L"CapsuleApp: Capsule FwType is invalid.\n");
> +    goto Done;
> +  }
> +
> +  FullCapsuleBufferSize = NESTED_CAPSULE_HEADER_SIZE + FileSize;
> +  FullCapsuleBuffer = AllocatePool(FullCapsuleBufferSize);
> +  if (FullCapsuleBuffer == NULL) {
> +    Print(L"CapsuleApp: Capsule Buffer size (0x%x) too big.\n",
> FullCapsuleBufferSize);
> +    Status = EFI_OUT_OF_RESOURCES;
> +    goto Done;
> +  }
> +
> +  NestedCapsuleHeader = (EFI_CAPSULE_HEADER *)FullCapsuleBuffer;
> +  ZeroMem(NestedCapsuleHeader, NESTED_CAPSULE_HEADER_SIZE);
> +  CopyGuid(&NestedCapsuleHeader->CapsuleGuid, ImageTypeId);
> +  NestedCapsuleHeader->HeaderSize = NESTED_CAPSULE_HEADER_SIZE;
> +  NestedCapsuleHeader->Flags = (FwType == ESRT_FW_TYPE_DEVICEFIRMWARE) ?
> SYSTEM_FIRMWARE_FLAG : DEVICE_FIRMWARE_FLAG;
> +  NestedCapsuleHeader->CapsuleImageSize = (UINT32)FullCapsuleBufferSize;
> +
> +  CopyMem((UINT8 *)NestedCapsuleHeader + NestedCapsuleHeader->HeaderSize,
> CapsuleBuffer, FileSize);
> +
> +  Status = WriteFileFromBuffer(OutputCapsuleName, FullCapsuleBufferSize,
> FullCapsuleBuffer);
> +  Print(L"CapsuleApp: Write %s %r\n", OutputCapsuleName, Status);
> +
> +Done:
> +  if (CapsuleBuffer != NULL) {
> +    FreePool(CapsuleBuffer);
> +  }
> +
> +  if (FullCapsuleBuffer != NULL) {
> +    FreePool(FullCapsuleBuffer);
> +  }
> +
> +  return Status;
> +}
> +
> +
> +/**
> +  Clear capsule status variable.
> +
> +  @retval EFI_SUCCESS            The capsule status variable is cleared.
> +**/
> +EFI_STATUS
> +ClearCapsuleStatusVariable(
> +  VOID
> +  )
> +{
> +  EFI_STATUS                          Status;
> +  UINT32                              Index;
> +  CHAR16                              CapsuleVarName[20];
> +  CHAR16                              *TempVarName;
> +
> +  StrCpyS (CapsuleVarName, sizeof(CapsuleVarName)/sizeof(CapsuleVarName[0]),
> L"Capsule");
> +  TempVarName = CapsuleVarName + StrLen (CapsuleVarName);
> +  Index = 0;
> +
> +  while (TRUE) {
> +    UnicodeSPrint (TempVarName, 5 * sizeof(CHAR16), L"%04x", Index);
> +
> +    Status = gRT->SetVariable (
> +                    CapsuleVarName,
> +                    &gEfiCapsuleReportGuid,
> +                    EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS |
> EFI_VARIABLE_BOOTSERVICE_ACCESS,
> +                    0,
> +                    (VOID *)NULL
> +                    );
> +    if (EFI_ERROR(Status)) {
> +      //
> +      // There is no capsule variables, quit
> +      //
> +      break;
> +    }
> +
> +    Index++;
> +    if (Index > 0xFFFF) {
> +      break;
> +    }
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Get the active UEFI system partition from bootoption list.
> +
> +  @param[out] Fs    Simple File System protocol on the active UEFI system partition
> +
> +  @retval EFI_SUCCESS   active UEFI system partition found
> +**/
> +EFI_STATUS
> +GetEfiSysPartition(
> +  OUT EFI_SIMPLE_FILE_SYSTEM_PROTOCOL **Fs
> +  )
> +{
> +  EFI_STATUS                       Status;
> +  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL  *FsTemp;
> +  UINTN                            NoHandles;
> +  EFI_HANDLE                       *Handles;
> +  UINTN                            Index;
> +
> +  Handles = NULL;
> +
> +  //
> +  // search for EFI system partition protocol on Boot option device path
> +  //
> +  Status = gBS->LocateHandleBuffer(ByProtocol, &gEfiPartTypeSystemPartGuid, NULL,
> &NoHandles, &Handles);
> +  if (EFI_ERROR(Status)) {
> +    return Status;
> +  }
> +
> +  //
> +  // Skip BootOptions within FV
> +  //
> +  for (Index = 0; Index < NoHandles; Index++) {
> +    Status = gBS->HandleProtocol (Handles[Index], &gEfiSimpleFileSystemProtocolGuid,
> (VOID **)&FsTemp);
> +    if (!EFI_ERROR (Status)){
> +      *Fs = FsTemp;
> +      break;
> +    }
> +  }
> +  return Status;
> +}
> +
> +/**
> +  Copy a list of capsule images to the active UEFI system partition from bootoption
> list.
> +
> +  @param[in] CapsuleBuffer    An array of pointer to capsule images
> +  @param[in] FileSize         An array of UINTN to capsule images size
> +  @param[in] CapsuleNum       The count of capsule images
> +
> +  @retval EFI_SUCCESS   Capsule images are copied to the active UEFI system partition
> +**/
> +EFI_STATUS
> +CopyCapsuleToActiveEfiPartition(
> +  IN VOID                          **CapsuleBuffer,
> +  IN UINTN                         *FileSize,
> +  IN UINTN                         CapsuleNum
> +  )
> +{
> +  EFI_STATUS                       Status;
> +  CHAR16                           *CapsuleName;
> +  UINTN                            Index;
> +  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL  *Fs;
> +  EFI_FILE_HANDLE                  RootDir;
> +  EFI_FILE_HANDLE                  CapsuleDir;
> +  EFI_FILE_HANDLE                  DestHandle;
> +  UINTN                            DataSize;
> +  UINT64                           OsIndication;
> +
> +  RootDir      = NULL;
> +  CapsuleDir   = NULL;
> +
> +  Status = GetEfiSysPartition(&Fs);
> +  if (EFI_ERROR(Status)) {
> +    Print (L"Can not find active UEFI System Partition\n");
> +    return Status;
> +  }
> +
> +  Status = Fs->OpenVolume(Fs, &RootDir);
> +  if (EFI_ERROR(Status)) {
> +    goto EXIT;
> +  }
> +
> +  Status = RootDir->Open(
> +                      RootDir,
> +                      &CapsuleDir,
> +                      EFI_CAPSULE_FROM_FILE_DIR,
> +                      EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE,
> +                      EFI_FILE_DIRECTORY
> +                      );
> +  if (EFI_ERROR(Status)) {
> +    goto EXIT;
> +  }
> +
> +  //
> +  // Read the input files.
> +  //
> +  for (Index = 0; Index < CapsuleNum; Index++) {
> +    CapsuleName = Argv[CapsuleFirstIndex + Index];
> +    Status = CapsuleDir->Open(
> +                           CapsuleDir,
> +                           &DestHandle,
> +                           CapsuleName,
> +                           EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE |
> EFI_FILE_MODE_CREATE,
> +                           EFI_FILE_ARCHIVE
> +                           );
> +    if (EFI_ERROR(Status)) {
> +      Print(L"CapsuleApp: %s open error - %r\n", CapsuleName, Status);
> +      continue;
> +    }
> +
> +    DataSize = FileSize[Index];
> +    Status = DestHandle->Write(
> +                           DestHandle,
> +                           &DataSize,
> +                           CapsuleBuffer[Index]
> +                           );
> +    DestHandle->Close(DestHandle);
> +    if (EFI_ERROR(Status)) {
> +      Print(L"CapsuleApp: %s write error - %r, FileSize - 0x%x\n", CapsuleName,
> Status, FileSize[Index]);
> +    }
> +  }
> +
> +  Status = gRT->GetVariable (
> +                  L"OsIndications",
> +                  &gEfiGlobalVariableGuid,
> +                  NULL,
> +                  &DataSize,
> +                  (VOID *) &OsIndication
> +                  );
> +
> +  if (EFI_ERROR(Status) || DataSize != sizeof(OsIndication)) {
> +    OsIndication = 0;
> +  }
> +
> +  //
> +  // Set OsIndications Variable EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED bit
> +  //
> +  OsIndication |= EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED;
> +  Status = gRT->SetVariable (
> +                  L"OsIndications",
> +                  &gEfiGlobalVariableGuid,
> +                  EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS |
> +                  EFI_VARIABLE_BOOTSERVICE_ACCESS,
> +                  sizeof(OsIndication),
> +                  (VOID *)&OsIndication
> +                  );
> +
> +
> +EXIT:
> +  if (RootDir != NULL) {
> +    RootDir->Close(RootDir);
> +  }
> +
> +  if (CapsuleDir != NULL) {
> +    CapsuleDir->Close(CapsuleDir);
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  Build Gather list for a list of capsule images.
> +
> +  @param[in]  CapsuleBuffer    An array of pointer to capsule images
> +  @param[in]  FileSize         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                         *FileSize,
> +  IN UINTN                         CapsuleNum,
> +  OUT EFI_CAPSULE_BLOCK_DESCRIPTOR **BlockDescriptors
> +  )
> +{
> +  EFI_STATUS                    Status;
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR  *BlockDescriptors1;
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR  *BlockDescriptors2;
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR  *BlockDescriptorPre;
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR  *BlockDescriptorsHeader;
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR  *TempBlockPtr;
> +  UINT8                         *TempDataPtr;
> +  UINTN                         SizeLeft;
> +  UINTN                         Size;
> +  INT32                         Count;
> +  INT32                         Number;
> +  UINTN                         Index;
> +
> +  TempBlockPtr           = NULL;
> +  BlockDescriptors1      = NULL;
> +  BlockDescriptors2      = NULL;
> +  BlockDescriptorPre     = NULL;
> +  BlockDescriptorsHeader = NULL;
> +
> +  for (Index = 0; Index < CapsuleNum; Index++) {
> +    //
> +    // Allocate memory for the descriptors.
> +    //
> +    if (NumberOfDescriptors == 1) {
> +      Count = 2;
> +    } else {
> +      Count = (INT32)(NumberOfDescriptors + 2) / 2;
> +    }
> +
> +    Size               = Count * sizeof (EFI_CAPSULE_BLOCK_DESCRIPTOR);
> +    BlockDescriptors1  = AllocateRuntimeZeroPool (Size);
> +    if (BlockDescriptors1 == NULL) {
> +      Print (L"CapsuleApp: failed to allocate memory for descriptors\n");
> +      Status = EFI_OUT_OF_RESOURCES;
> +      goto ERREXIT;
> +    } else {
> +      Print (L"CapsuleApp: creating capsule descriptors at 0x%X\n", (UINTN)
> BlockDescriptors1);
> +      Print (L"CapsuleApp: capsule data starts          at 0x%X with size 0x%X\n",
> (UINTN) CapsuleBuffer, FileSize);
> +    }
> +
> +    //
> +    // Record descirptor header
> +    //
> +    if (Index == 0) {
> +      BlockDescriptorsHeader = BlockDescriptors1;
> +    }
> +
> +    if (BlockDescriptorPre != NULL) {
> +      BlockDescriptorPre->Union.ContinuationPointer = (UINTN) BlockDescriptors1;
> +      BlockDescriptorPre->Length = 0;
> +    }
> +
> +    //
> +    // Fill them in
> +    //
> +    TempBlockPtr  = BlockDescriptors1;
> +    TempDataPtr   = CapsuleBuffer[Index];
> +    SizeLeft      = FileSize[Index];
> +    for (Number = 0; (Number < Count - 1) && (SizeLeft != 0); Number++) {
> +      //
> +      // Divide remaining data in half
> +      //
> +      if (NumberOfDescriptors != 1) {
> +        if (SizeLeft == 1) {
> +          Size = 1;
> +        } else {
> +          Size = SizeLeft / 2;
> +        }
> +      } else {
> +        Size = SizeLeft;
> +      }
> +      TempBlockPtr->Union.DataBlock    = (UINTN)TempDataPtr;
> +      TempBlockPtr->Length  = Size;
> +      Print (L"CapsuleApp: capsule block/size              0x%X/0x%X\n", (UINTN)
> TempDataPtr, Size);
> +      SizeLeft -= Size;
> +      TempDataPtr += Size;
> +      TempBlockPtr++;
> +    }
> +
> +    //
> +    // Allocate the second list, point the first block's last entry to point
> +    // to this one, and fill this one in. Worst case is that the previous
> +    // list only had one element that pointed here, so we need at least two
> +    // elements -- one to point to all the data, another to terminate the list.
> +    //
> +    if ((NumberOfDescriptors != 1) && (SizeLeft != 0)) {
> +      Count = (INT32)(NumberOfDescriptors + 2) - Count;
> +      if (Count == 1) {
> +        Count++;
> +      }
> +
> +      Size              = Count * sizeof (EFI_CAPSULE_BLOCK_DESCRIPTOR);
> +      BlockDescriptors2 = AllocateRuntimeZeroPool (Size);
> +      if (BlockDescriptors2 == NULL) {
> +        Print (L"CapsuleApp: failed to allocate memory for descriptors\n");
> +        Status = EFI_OUT_OF_RESOURCES;
> +        goto ERREXIT;
> +      }
> +
> +      //
> +      // Point the first list's last element to point to this second list.
> +      //
> +      TempBlockPtr->Union.ContinuationPointer   = (UINTN) BlockDescriptors2;
> +
> +      TempBlockPtr->Length  = 0;
> +      TempBlockPtr = BlockDescriptors2;
> +      for (Number = 0; Number < Count - 1; Number++) {
> +        //
> +        // If second-to-last one, then dump rest to this element
> +        //
> +        if (Number == (Count - 2)) {
> +          Size = SizeLeft;
> +        } else {
> +          //
> +          // Divide remaining data in half
> +          //
> +          if (SizeLeft == 1) {
> +            Size = 1;
> +          } else {
> +            Size = SizeLeft / 2;
> +          }
> +        }
> +
> +        TempBlockPtr->Union.DataBlock    = (UINTN)TempDataPtr;
> +        TempBlockPtr->Length  = Size;
> +        Print (L"CapsuleApp: capsule block/size              0x%X/0x%X\n", (UINTN)
> TempDataPtr, Size);
> +        SizeLeft -= Size;
> +        TempDataPtr += Size;
> +        TempBlockPtr++;
> +        if (SizeLeft == 0) {
> +          break;
> +        }
> +      }
> +    }
> +
> +    BlockDescriptorPre = TempBlockPtr;
> +    BlockDescriptors1  = NULL;
> +  }
> +
> +  //
> +  // Null-terminate.
> +  //
> +  if (TempBlockPtr != NULL) {
> +    TempBlockPtr->Union.ContinuationPointer    = (UINTN)NULL;
> +    TempBlockPtr->Length  = 0;
> +    *BlockDescriptors = BlockDescriptorsHeader;
> +  }
> +
> +  return EFI_SUCCESS;
> +
> +ERREXIT:
> +  if (BlockDescriptors1 != NULL) {
> +    FreePool(BlockDescriptors1);
> +  }
> +
> +  if (BlockDescriptors2 != NULL) {
> +    FreePool(BlockDescriptors2);
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  Clear the Gather list for a list of capsule images.
> +
> +  @param[in]  BlockDescriptors The block descriptors for the capsule images
> +  @param[in]  CapsuleNum       The count of capsule images
> +**/
> +VOID
> +CleanGatherList(
> +  IN EFI_CAPSULE_BLOCK_DESCRIPTOR   *BlockDescriptors,
> +  IN UINTN                          CapsuleNum
> +  )
> +{
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR   *TempBlockPtr;
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR   *TempBlockPtr1;
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR   *TempBlockPtr2;
> +  UINTN                          Index;
> +
> +  if (BlockDescriptors != NULL) {
> +    TempBlockPtr1 = BlockDescriptors;
> +    while (1){
> +      TempBlockPtr = TempBlockPtr1;
> +      for (Index = 0; Index < CapsuleNum; Index++) {
> +        if (TempBlockPtr[Index].Length == 0) {
> +          break;
> +        }
> +      }
> +
> +      if (TempBlockPtr[Index].Union.ContinuationPointer == (UINTN)NULL) {
> +        break;
> +      }
> +
> +      TempBlockPtr2 = (VOID *) ((UINTN) TempBlockPtr->Union.ContinuationPointer);
> +      FreePool(TempBlockPtr1);
> +      TempBlockPtr1 = TempBlockPtr2;
> +    }
> +  }
> +}
> +
> +/**
> +  Print APP usage.
> +**/
> +VOID
> +PrintUsage (
> +  VOID
> +  )
> +{
> +  Print(L"CapsuleApp:  usage\n");
> +  Print(L"  CapsuleApp [-F] <Capsule...> [-NR]\n");
> +  Print(L"  CapsuleApp -S\n");
> +  Print(L"  CapsuleApp -C\n");
> +  Print(L"  CapsuleApp -P\n");
> +  Print(L"  CapsuleApp -E\n");
> +  Print(L"  CapsuleApp -G <BMP> -O <Capsule>\n");
> +  Print(L"  CapsuleApp -N <Capsule> -O <NestedCapsule>\n");
> +  Print(L"  CapsuleApp -D|-DS <Capsule>\n");
> +  Print(L"Parameter:\n");
> +  Print(L"  -F:  Put capsule file to disk.\n");
> +  Print(L"       No -F means to put capsule file in memory.\n");
> +  Print(L"  -NR: No Reset.\n");
> +  Print(L"  -S:  Dump capsule status.\n");
> +  Print(L"  -C:  Clear capsule status.\n");
> +  Print(L"  -P:  Dump FMP protocol info.\n");
> +  Print(L"  -E:  Dump ESRT table info.\n");
> +  Print(L"  -G:  Input BMP file name\n");
> +  Print(L"  -N:  Append Capsule Header accroding to Windows Firmware Update\n");
> +  Print(L"  -O:  Output Capsule file name\n");
> +  Print(L"  -D:  Dump Capsule\n");
> +  Print(L"  -DS: Dump Capsule with System FMP format\n");
> +}
> +
> +/**
> +  Update Capsule image.
> +
> +  @param[in]  ImageHandle     The image handle.
> +  @param[in]  SystemTable     The system table.
> +
> +  @retval EFI_SUCCESS            Command completed successfully.
> +  @retval EFI_INVALID_PARAMETER  Command usage error.
> +  @retval EFI_NOT_FOUND          The input file can't be found.
> +**/
> +EFI_STATUS
> +EFIAPI
> +UefiMain (
> +  IN EFI_HANDLE        ImageHandle,
> +  IN EFI_SYSTEM_TABLE  *SystemTable
> +  )
> +{
> +  EFI_STATUS                    Status;
> +  UINTN                         FileSize[MAX_CAPSULE_NUM];
> +  VOID                          *CapsuleBuffer[MAX_CAPSULE_NUM];
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR  *BlockDescriptors;
> +  EFI_CAPSULE_HEADER             *CapsuleHeaderArray[MAX_CAPSULE_NUM + 1];
> +  UINT64                         MaxCapsuleSize;
> +  EFI_RESET_TYPE                 ResetType;
> +  BOOLEAN                        NeedReset;
> +  BOOLEAN                        NoReset;
> +  BOOLEAN                        NeedCopyOnDisk;
> +  CHAR16                         *CapsuleName;
> +  UINTN                          CapsuleNum;
> +  UINTN                          Index;
> +
> +  Status = GetArg();
> +  if (EFI_ERROR(Status)) {
> +    PrintUsage();
> +    return Status;
> +  }
> +  if (Argc < 2) {
> +    PrintUsage();
> +    CleanArg();
> +    return EFI_INVALID_PARAMETER;
> +  }
> +  if ((StrCmp(Argv[1], L"-D") == 0) ||
> +      (StrCmp(Argv[1], L"-DS") == 0)) {
> +    Status = DumpCapsule();
> +    CleanArg();
> +    return Status;
> +  }
> +  if (StrCmp(Argv[1], L"-G") == 0) {
> +    Status = CreateBmpFmp();
> +    CleanArg();
> +    return Status;
> +  }
> +  if (StrCmp(Argv[1], L"-N") == 0) {
> +    Status = CreateNestedFmp();
> +    CleanArg();
> +    return Status;
> +  }
> +  if (StrCmp(Argv[1], L"-S") == 0) {
> +    Status = DmpCapsuleStatusVariable();
> +    CleanArg();
> +    return EFI_SUCCESS;
> +  }
> +  if (StrCmp(Argv[1], L"-C") == 0) {
> +    Status = ClearCapsuleStatusVariable();
> +    CleanArg();
> +    return Status;
> +  }
> +  if (StrCmp(Argv[1], L"-P") == 0) {
> +    DumpFmpData();
> +    CleanArg();
> +    return EFI_SUCCESS;
> +  }
> +  if (StrCmp(Argv[1], L"-E") == 0) {
> +    DumpEsrtData();
> +    CleanArg();
> +    return EFI_SUCCESS;
> +  }
> +  if (StrCmp(Argv[1], L"-F") == 0) {
> +    NeedCopyOnDisk = TRUE;
> +    CapsuleFirstIndex = 2;
> +  } else {
> +    NeedCopyOnDisk = FALSE;
> +    CapsuleFirstIndex = 1;
> +  }
> +  if (StrCmp(Argv[Argc - 1], L"-NR") == 0) {
> +    NoReset = TRUE;
> +    CapsuleLastIndex = Argc - 2;
> +  } else {
> +    NoReset = FALSE;
> +    CapsuleLastIndex = Argc - 1;
> +  }
> +  CapsuleNum = CapsuleLastIndex - CapsuleFirstIndex + 1;
> +
> +  if (CapsuleFirstIndex > CapsuleLastIndex) {
> +    Print(L"CapsuleApp: NO capsule image.\n");
> +    CleanArg();
> +    return EFI_UNSUPPORTED;
> +  }
> +  if (CapsuleNum > MAX_CAPSULE_NUM) {
> +    Print(L"CapsuleApp: Too many capsule images.\n");
> +    CleanArg();
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  ZeroMem(&CapsuleBuffer, sizeof(CapsuleBuffer));
> +  ZeroMem(&FileSize, sizeof(FileSize));
> +  BlockDescriptors = NULL;
> +
> +  for (Index = 0; Index < CapsuleNum; Index++) {
> +    CapsuleName = Argv[CapsuleFirstIndex + Index];
> +    Status = ReadFileToBuffer(CapsuleName, &FileSize[Index], &CapsuleBuffer[Index]);
> +    if (EFI_ERROR(Status)) {
> +      Print(L"CapsuleApp: capsule image (%s) is not found.\n", CapsuleName);
> +      goto Done;
> +    }
> +  }
> +
> +  if (NeedCopyOnDisk) {
> +    Status = CopyCapsuleToActiveEfiPartition(CapsuleBuffer, FileSize, CapsuleNum);
> +  } else {
> +    //
> +    // Every capsule use 2 descriptor 1 for data 1 for end
> +    //
> +    Status = BuildGatherList(CapsuleBuffer, FileSize, CapsuleNum, &BlockDescriptors);
> +  }
> +  if (EFI_ERROR(Status)) {
> +    goto Done;
> +  }
> +
> +  //
> +  // Call the runtime service capsule.
> +  //
> +  NeedReset = FALSE;
> +  for (Index = 0; Index < CapsuleNum; Index++) {
> +    CapsuleHeaderArray[Index] = (EFI_CAPSULE_HEADER *) CapsuleBuffer[Index];
> +    if ((CapsuleHeaderArray[Index]->Flags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET) != 0)
> {
> +      NeedReset = TRUE;
> +    }
> +  }
> +  CapsuleHeaderArray[CapsuleNum] = NULL;
> +  if (NoReset) {
> +    NeedReset = FALSE;
> +  }
> +
> +  //
> +  // Inquire platform capability of UpdateCapsule.
> +  //
> +  Status = gRT->QueryCapsuleCapabilities (CapsuleHeaderArray, CapsuleNum,
> &MaxCapsuleSize, &ResetType);
> +  if (EFI_ERROR(Status)) {
> +    Print (L"CapsuleApp: failed to query capsule capability - %r\n", Status);
> +    goto Done;
> +  }
> +
> +  for (Index = 0; Index < CapsuleNum; Index++) {
> +    if (FileSize[Index] > MaxCapsuleSize) {
> +      Print (L"CapsuleApp: capsule is too large to update, %ld is allowed\n",
> MaxCapsuleSize);
> +      Status = EFI_UNSUPPORTED;
> +      goto Done;
> +    }
> +  }
> +
> +  //
> +  // Check whether the input capsule image has the flag of persist across system
> reset.
> +  //
> +  if (NeedReset) {
> +    Status = gRT->UpdateCapsule(CapsuleHeaderArray,CapsuleNum,(UINTN)
> BlockDescriptors);
> +    if (Status != EFI_SUCCESS) {
> +      Print (L"CapsuleApp: failed to update capsule - %r\n", Status);
> +      goto Done;
> +    }
> +    //
> +    // For capsule who has reset flag, after calling UpdateCapsule service,triger a
> +    // system reset to process capsule persist across a system reset.
> +    //
> +    gRT->ResetSystem (ResetType, EFI_SUCCESS, 0, NULL);
> +  } else {
> +    //
> +    // For capsule who has no reset flag, only call UpdateCapsule Service without a
> +    // system reset. The service will process the capsule immediately.
> +    //
> +    Status = gRT->UpdateCapsule (CapsuleHeaderArray,CapsuleNum,(UINTN)
> BlockDescriptors);
> +    if (Status != EFI_SUCCESS) {
> +      Print (L"CapsuleApp: failed to update capsule - %r\n", Status);
> +    }
> +  }
> +
> +  Status = EFI_SUCCESS;
> +
> +Done:
> +  for (Index = 0; Index < CapsuleNum; Index++) {
> +    if (CapsuleBuffer[Index] != NULL) {
> +      FreePool (CapsuleBuffer[Index]);
> +    }
> +  }
> +
> +  CleanGatherList(BlockDescriptors, CapsuleNum);
> +  CleanArg();
> +
> +  return Status;
> +}
> diff --git a/MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf
> b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf
> new file mode 100644
> index 0000000..7ee44fc
> --- /dev/null
> +++ b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf
> @@ -0,0 +1,71 @@
> +##  @file
> +#  A shell application that triggers capsule update process.
> +#
> +# This application can trigger capsule update process. It can also
> +# generate capsule image, or dump capsule variable information.
> +#
> +#  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
> +#  This program and the accompanying materials
> +#  are licensed and made available under the terms and conditions of the BSD License
> +#  which accompanies this distribution.  The full text of the license may be found at
> +#  http://opensource.org/licenses/bsd-license.php
> +#
> +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +#
> +##
> +
> +[Defines]
> +  INF_VERSION                    = 0x00010006
> +  BASE_NAME                      = CapsuleApp
> +  MODULE_UNI_FILE                = CapsuleApp.uni
> +  FILE_GUID                      = 4CEF31DA-8682-4274-9CC4-AEE7516A5E7B
> +  MODULE_TYPE                    = UEFI_APPLICATION
> +  VERSION_STRING                 = 1.0
> +  ENTRY_POINT                    = UefiMain
> +
> +#
> +# The following information is for reference only and not required by the build tools.
> +#
> +#  VALID_ARCHITECTURES           = IA32 X64
> +#
> +
> +[Sources]
> +  CapsuleApp.c
> +  CapsuleDump.c
> +  AppSupport.c
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +
> +[Guids]
> +  gEfiFileInfoGuid
> +  gEfiPartTypeSystemPartGuid
> +  gEfiGlobalVariableGuid
> +  gEfiCapsuleReportGuid
> +  gEfiFmpCapsuleGuid
> +  gWindowsUxCapsuleGuid
> +  gEfiCertTypeRsa2048Sha256Guid
> +  gEfiCertPkcs7Guid
> +  gEfiSystemResourceTableGuid
> +
> +[Protocols]
> +  gEfiLoadedImageProtocolGuid
> +  gEfiSimpleFileSystemProtocolGuid
> +  gEfiGraphicsOutputProtocolGuid
> +  gEfiFirmwareManagementProtocolGuid
> +
> +[LibraryClasses]
> +  BaseLib
> +  UefiApplicationEntryPoint
> +  DebugLib
> +  MemoryAllocationLib
> +  UefiBootServicesTableLib
> +  UefiRuntimeServicesTableLib
> +  UefiLib
> +  PrintLib
> +  EdkiiSystemCapsuleLib
> +
> +[UserExtensions.TianoCore."ExtraFiles"]
> +  CapsuleAppExtra.uni
> diff --git a/MdeModulePkg/Application/CapsuleApp/CapsuleApp.uni
> b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.uni
> new file mode 100644
> index 0000000..54d6e12
> --- /dev/null
> +++ b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.uni
> @@ -0,0 +1,22 @@
> +// /** @file
> +// A shell application that triggers capsule update process.
> +//
> +// This application can trigger capsule update process. It can also
> +// generate capsule image, or dump capsule variable information.
> +//
> +// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
> +//
> +// This program and the accompanying materials
> +// are licensed and made available under the terms and conditions of the BSD License
> +// which accompanies this distribution. The full text of the license may be found at
> +// http://opensource.org/licenses/bsd-license.php
> +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +//
> +// **/
> +
> +
> +#string STR_MODULE_ABSTRACT             #language en-US "A shell application that
> triggers capsule update process."
> +
> +#string STR_MODULE_DESCRIPTION          #language en-US "This application can trigger
> capsule update process. It can also generate capsule image, or dump capsule variable
> information."
> +
> diff --git a/MdeModulePkg/Application/CapsuleApp/CapsuleAppExtra.uni
> b/MdeModulePkg/Application/CapsuleApp/CapsuleAppExtra.uni
> new file mode 100644
> index 0000000..b5a8840
> --- /dev/null
> +++ b/MdeModulePkg/Application/CapsuleApp/CapsuleAppExtra.uni
> @@ -0,0 +1,19 @@
> +// /** @file
> +// CapsuleApp Localized Strings and Content
> +//
> +// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
> +//
> +// This program and the accompanying materials
> +// are licensed and made available under the terms and conditions of the BSD License
> +// which accompanies this distribution. The full text of the license may be found at
> +// http://opensource.org/licenses/bsd-license.php
> +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +//
> +// **/
> +
> +#string STR_PROPERTIES_MODULE_NAME
> +#language en-US
> +"Capsule Application"
> +
> +
> diff --git a/MdeModulePkg/Application/CapsuleApp/CapsuleDump.c
> b/MdeModulePkg/Application/CapsuleApp/CapsuleDump.c
> new file mode 100644
> index 0000000..c56f41f
> --- /dev/null
> +++ b/MdeModulePkg/Application/CapsuleApp/CapsuleDump.c
> @@ -0,0 +1,840 @@
> +/** @file
> +  Dump Capsule image information.
> +
> +  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the BSD License
> +  which accompanies this distribution.  The full text of the license may be found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +
> +**/
> +
> +#include <PiDxe.h>
> +#include <Library/BaseLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/UefiRuntimeServicesTableLib.h>
> +#include <Library/UefiLib.h>
> +#include <Library/PrintLib.h>
> +#include <Library/EdkiiSystemCapsuleLib.h>
> +#include <Protocol/FirmwareManagement.h>
> +#include <Guid/ImageAuthentication.h>
> +#include <Guid/EdkiiSystemFmpCapsule.h>
> +#include <Guid/CapsuleReport.h>
> +#include <Guid/SystemResourceTable.h>
> +#include <Guid/FmpCapsule.h>
> +#include <IndustryStandard/WindowsUxCapsule.h>
> +
> +/**
> +  Read a file.
> +
> +  @param FileName        The file to be read.
> +  @param BufferSize      The file buffer size
> +  @param Buffer          The file buffer
> +
> +  @retval EFI_SUCCESS    Read file successfully
> +  @retval EFI_NOT_FOUND  File not found
> +**/
> +EFI_STATUS
> +ReadFileToBuffer(
> +  IN  CHAR16                               *FileName,
> +  OUT UINTN                                *BufferSize,
> +  OUT VOID                                 **Buffer
> +  );
> +
> +extern UINTN  Argc;
> +extern CHAR16 *Argv[];
> +
> +/**
> +  Dump UX capsule information.
> +
> +  @param CapsuleHeader      The UX capsule header
> +**/
> +VOID
> +DumpUxCapsule(
> +  IN EFI_CAPSULE_HEADER  *CapsuleHeader
> +  )
> +{
> +  EFI_DISPLAY_CAPSULE                           *DisplayCapsule;
> +  DisplayCapsule = (EFI_DISPLAY_CAPSULE *)CapsuleHeader;
> +  Print(L"[UxCapusule]\n");
> +  Print(L"CapsuleHeader:\n");
> +  Print(L"  CapsuleGuid      - %g\n", &DisplayCapsule->CapsuleHeader.CapsuleGuid);
> +  Print(L"  HeaderSize       - 0x%x\n", DisplayCapsule->CapsuleHeader.HeaderSize);
> +  Print(L"  Flags            - 0x%x\n", DisplayCapsule->CapsuleHeader.Flags);
> +  Print(L"  CapsuleImageSize - 0x%x\n", DisplayCapsule-
> >CapsuleHeader.CapsuleImageSize);
> +  Print(L"ImagePayload:\n");
> +  Print(L"  Version          - 0x%x\n", DisplayCapsule->ImagePayload.Version);
> +  Print(L"  Checksum         - 0x%x\n", DisplayCapsule->ImagePayload.Checksum);
> +  Print(L"  ImageType        - 0x%x\n", DisplayCapsule->ImagePayload.ImageType);
> +  Print(L"  Mode             - 0x%x\n", DisplayCapsule->ImagePayload.Mode);
> +  Print(L"  OffsetX          - 0x%x\n", DisplayCapsule->ImagePayload.OffsetX);
> +  Print(L"  OffsetY          - 0x%x\n", DisplayCapsule->ImagePayload.OffsetY);
> +}
> +
> +/**
> +  Dump FMP image authentication information.
> +
> +  @param Image      The FMP capsule image
> +  @param ImageSize  The size of the FMP capsule image in bytes.
> +
> +  @return the size of FMP authentication.
> +**/
> +UINTN
> +DumpImageAuthentication(
> +  IN VOID   *Image,
> +  IN UINTN  ImageSize
> +  )
> +{
> +  EFI_FIRMWARE_IMAGE_AUTHENTICATION             *ImageAuthentication;
> +
> +  ImageAuthentication = Image;
> +  if (CompareGuid(&ImageAuthentication->AuthInfo.CertType, &gEfiCertPkcs7Guid) ||
> +      CompareGuid(&ImageAuthentication->AuthInfo.CertType,
> &gEfiCertTypeRsa2048Sha256Guid)) {
> +    Print(L"[ImageAuthentication]\n");
> +    Print(L"  MonotonicCount   - 0x%lx\n", ImageAuthentication->MonotonicCount);
> +    Print(L"WIN_CERTIFICATE:\n");
> +    Print(L"  dwLength         - 0x%x\n", ImageAuthentication->AuthInfo.Hdr.dwLength);
> +    Print(L"  wRevision        - 0x%x\n", ImageAuthentication-
> >AuthInfo.Hdr.wRevision);
> +    Print(L"  wCertificateType - 0x%x\n", ImageAuthentication-
> >AuthInfo.Hdr.wCertificateType);
> +    Print(L"  CertType         - %g\n", &ImageAuthentication->AuthInfo.CertType);
> +    return sizeof(ImageAuthentication->MonotonicCount) + ImageAuthentication-
> >AuthInfo.Hdr.dwLength;
> +  } else {
> +    return 0;
> +  }
> +}
> +
> +/**
> +  Dump EDKII system FMP capsule.
> +
> +  @param Image      The EDKII system FMP capsule.
> +  @param ImageSize  The size of the EDKII system FMP capsule in bytes.
> +**/
> +VOID
> +DumpEdkiiSystemFmpCapsule(
> +  IN VOID   *Image,
> +  IN UINTN  ImageSize
> +  )
> +{
> +  UINTN                                         ImageOffset;
> +  VOID                                          *BiosImage;
> +  UINTN                                         BiosImageSize;
> +  BOOLEAN                                       Result;
> +  EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR        *TempImageFmpInfo;
> +  EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR        *ImageFmpInfo;
> +  UINTN                                         ImageFmpInfoSize;
> +
> +  //
> +  // We do not know if there is EFI_FIRMWARE_IMAGE_AUTHENTICATION.
> +  // so just *try* to parse it
> +  //
> +  ImageOffset = DumpImageAuthentication(Image, ImageSize);
> +  Image = (UINT8 *)Image + ImageOffset;
> +  ImageSize -= ImageOffset;
> +  Print(L"[Image]\n");
> +  Print(L"  ImageSize   - 0x%x\n", ImageSize);
> +
> +  Result = ExtractConfigImage(Image, ImageSize, &BiosImage, &BiosImageSize);
> +  if (Result) {
> +    Print(L"  ConfigFileSize  - 0x%x\n", BiosImageSize);
> +  }
> +  Result = ExtractDriverFvImage(Image, ImageSize, &BiosImage, &BiosImageSize);
> +  if (Result) {
> +    Print(L"  DriverFvSize    - 0x%x\n", BiosImageSize);
> +  }
> +  Result = ExtractSystemFirmwareImage(Image, ImageSize, &BiosImage, &BiosImageSize);
> +  if (Result) {
> +    Print(L"  BiosImageSize   - 0x%x\n", BiosImageSize);
> +  }
> +  Result = ExtractSystemFirmwareImageFmpInfo(BiosImage, BiosImageSize,
> &TempImageFmpInfo, &ImageFmpInfoSize);
> +  if (Result) {
> +    ImageFmpInfo = AllocateCopyPool(ImageFmpInfoSize, TempImageFmpInfo);
> +    if (ImageFmpInfo != NULL) {
> +      Print(L"[ImageFmpInfo]\n");
> +      Print(L"  Signature                      - 0x%x\n", ImageFmpInfo->Signature);
> +      Print(L"  HeaderLength                   - 0x%x\n", ImageFmpInfo->HeaderLength);
> +      Print(L"  Length                         - 0x%x\n", ImageFmpInfo->Length);
> +      Print(L"  PackageVersion                 - 0x%x\n", ImageFmpInfo-
> >PackageVersion);
> +      Print(L"  PackageVersionNameStringOffset - 0x%x\n", ImageFmpInfo-
> >PackageVersionNameStringOffset);
> +      if (ImageFmpInfo->PackageVersionNameStringOffset != 0) {
> +        Print(L"                                 - %s\n", (UINT8 *)ImageFmpInfo +
> ImageFmpInfo->PackageVersionNameStringOffset);
> +      }
> +      Print(L"  ImageIndex                     - 0x%x\n", ImageFmpInfo->ImageIndex);
> +      Print(L"  ImageTypeId                    - %g\n", &ImageFmpInfo->ImageTypeId);
> +      Print(L"  ImageId                        - 0x%lx\n", ImageFmpInfo->ImageId);
> +      Print(L"  ImageIdNameStringOffset        - 0x%x\n", ImageFmpInfo-
> >ImageIdNameStringOffset);
> +      if (ImageFmpInfo->ImageIdNameStringOffset != 0) {
> +        Print(L"                                 - %s\n", (UINT8 *)ImageFmpInfo +
> ImageFmpInfo->ImageIdNameStringOffset);
> +      }
> +      Print(L"  Version                        - 0x%x\n", ImageFmpInfo->Version);
> +      Print(L"  VersionNameStringOffset        - 0x%x\n", ImageFmpInfo-
> >VersionNameStringOffset);
> +      if (ImageFmpInfo->VersionNameStringOffset != 0) {
> +        Print(L"                                 - %s\n", (UINT8 *)ImageFmpInfo +
> ImageFmpInfo->VersionNameStringOffset);
> +      }
> +      Print(L"  Size                           - 0x%lx\n", ImageFmpInfo->Size);
> +      Print(L"  AttributesSupported            - 0x%lx\n", ImageFmpInfo-
> >AttributesSupported);
> +      Print(L"  AttributesSetting              - 0x%lx\n", ImageFmpInfo-
> >AttributesSetting);
> +      Print(L"  Compatibilities                - 0x%lx\n", ImageFmpInfo-
> >Compatibilities);
> +      Print(L"  LowestSupportedImageVersion    - 0x%x\n", ImageFmpInfo-
> >LowestSupportedImageVersion);
> +      Print(L"  LastAttemptVersion             - 0x%x\n", ImageFmpInfo-
> >LastAttemptVersion);
> +      Print(L"  LastAttemptStatus              - 0x%x\n", ImageFmpInfo-
> >LastAttemptStatus);
> +      Print(L"  HardwareInstance               - 0x%lx\n", ImageFmpInfo-
> >HardwareInstance);
> +      Print(L"  Version                        - 0x%x\n", ImageFmpInfo->Version);
> +      FreePool(ImageFmpInfo);
> +    }
> +  }
> +}
> +
> +/**
> +  Dump a non-nested FMP capsule.
> +
> +  @param  CapsuleHeader  A pointer to CapsuleHeader
> +  @param  IsSystemFmp    If it is a system FMP
> +**/
> +VOID
> +DumpFmpCapsule(
> +  IN EFI_CAPSULE_HEADER  *CapsuleHeader,
> +  IN BOOLEAN             IsSystemFmp
> +  )
> +{
> +  EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER        *FmpCapsuleHeader;
> +  UINT64                                        *ItemOffsetList;
> +  UINTN                                         Index;
> +  UINTN                                         Count;
> +  EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER  *FmpImageHeader;
> +  VOID                                          *Image;
> +
> +  Print(L"[FmpCapusule]\n");
> +  Print(L"CapsuleHeader:\n");
> +  Print(L"  CapsuleGuid      - %g\n", &CapsuleHeader->CapsuleGuid);
> +  Print(L"  HeaderSize       - 0x%x\n", CapsuleHeader->HeaderSize);
> +  Print(L"  Flags            - 0x%x\n", CapsuleHeader->Flags);
> +  Print(L"  CapsuleImageSize - 0x%x\n", CapsuleHeader->CapsuleImageSize);
> +
> +  FmpCapsuleHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *)((UINT8 *)CapsuleHeader
> + CapsuleHeader->HeaderSize);
> +  ItemOffsetList = (UINT64 *)(FmpCapsuleHeader + 1);
> +  Print(L"FmpHeader:\n");
> +  Print(L"  Version             - 0x%x\n", FmpCapsuleHeader->Version);
> +  Print(L"  EmbeddedDriverCount - 0x%x\n", FmpCapsuleHeader->EmbeddedDriverCount);
> +  Print(L"  PayloadItemCount    - 0x%x\n", FmpCapsuleHeader->PayloadItemCount);
> +  Count = FmpCapsuleHeader->EmbeddedDriverCount + FmpCapsuleHeader->PayloadItemCount;
> +  for (Index = 0; Index < Count; Index++) {
> +    Print(L"  Offset[%d]           - 0x%x\n", Index, ItemOffsetList[Index]);
> +  }
> +
> +  for (Index = FmpCapsuleHeader->EmbeddedDriverCount; Index < Count; Index++) {
> +    Print(L"FmpPayload[%d] ImageHeader:\n", Index);
> +    FmpImageHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *)((UINT8
> *)FmpCapsuleHeader + ItemOffsetList[Index]);
> +    Print(L"  Version                - 0x%x\n", FmpImageHeader->Version);
> +    Print(L"  UpdateImageTypeId      - %g\n", &FmpImageHeader->UpdateImageTypeId);
> +    Print(L"  UpdateImageIndex       - 0x%x\n", FmpImageHeader->UpdateImageIndex);
> +    Print(L"  UpdateImageSize        - 0x%x\n", FmpImageHeader->UpdateImageSize);
> +    Print(L"  UpdateVendorCodeSize   - 0x%x\n", FmpImageHeader->UpdateVendorCodeSize);
> +    if (FmpImageHeader->Version >=
> EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {
> +      Print(L"  UpdateHardwareInstance - 0x%lx\n", FmpImageHeader-
> >UpdateHardwareInstance);
> +    }
> +    if (FmpImageHeader->Version >=
> EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {
> +      Image = (UINT8 *)(FmpImageHeader + 1);
> +    }  else {
> +      Image = (UINT8 *)FmpImageHeader +
> OFFSET_OF(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER, UpdateHardwareInstance);
> +    }
> +    if (IsSystemFmp) {
> +      DumpEdkiiSystemFmpCapsule(Image, FmpImageHeader->UpdateImageSize);
> +    }
> +  }
> +}
> +
> +/**
> +  Return if there is a FMP header below capsule header.
> +
> +  @param[in] CapsuleHeader A pointer to EFI_CAPSULE_HEADER
> +
> +  @retval TRUE  There is a FMP header below capsule header.
> +  @retval FALSE There is not a FMP header below capsule header
> +**/
> +BOOLEAN
> +IsNestedFmpCapsule(
> +  IN EFI_CAPSULE_HEADER         *CapsuleHeader
> +  )
> +{
> +  EFI_STATUS                 Status;
> +  EFI_SYSTEM_RESOURCE_TABLE  *Esrt;
> +  EFI_SYSTEM_RESOURCE_ENTRY  *EsrtEntry;
> +  UINTN                      Index;
> +  BOOLEAN                    EsrtGuidFound;
> +  EFI_CAPSULE_HEADER         *NestedCapsuleHeader;
> +  UINTN                      NestedCapsuleSize;
> +
> +  //
> +  // Check ESRT
> +  //
> +  EsrtGuidFound = FALSE;
> +  Status = EfiGetSystemConfigurationTable(&gEfiSystemResourceTableGuid, (VOID
> **)&Esrt);
> +  if (!EFI_ERROR(Status)) {
> +    EsrtEntry = (VOID *)(Esrt + 1);
> +    for (Index = 0; Index < Esrt->FwResourceCount; Index++, EsrtEntry++) {
> +      if (CompareGuid(&EsrtEntry->FwClass, &CapsuleHeader->CapsuleGuid)) {
> +        EsrtGuidFound = TRUE;
> +        break;
> +      }
> +    }
> +  }
> +
> +  if (!EsrtGuidFound) {
> +    return FALSE;
> +  }
> +
> +  //
> +  // Check nested capsule header
> +  // FMP GUID after ESRT one
> +  //
> +  NestedCapsuleHeader = (EFI_CAPSULE_HEADER *)((UINT8 *)CapsuleHeader + CapsuleHeader-
> >HeaderSize);
> +  NestedCapsuleSize = (UINTN)CapsuleHeader + CapsuleHeader->HeaderSize -
> (UINTN)NestedCapsuleHeader;
> +  if (NestedCapsuleSize < sizeof(EFI_CAPSULE_HEADER)) {
> +    return FALSE;
> +  }
> +  if (!CompareGuid(&NestedCapsuleHeader->CapsuleGuid, &gEfiFmpCapsuleGuid)) {
> +    return FALSE;
> +  }
> +  return TRUE;
> +}
> +
> +/**
> +  Dump capsule information
> +
> +  @retval EFI_SUCCESS            The capsule information is dumped.
> +  @retval EFI_UNSUPPORTED        Input parameter is not valid.
> +**/
> +EFI_STATUS
> +DumpCapsule(
> +  VOID
> +  )
> +{
> +  CHAR16                                        *CapsuleName;
> +  VOID                                          *Buffer;
> +  UINTN                                         FileSize;
> +  BOOLEAN                                       IsSystemFmp;
> +  EFI_CAPSULE_HEADER                            *CapsuleHeader;
> +  EFI_STATUS                                    Status;
> +
> +  if (Argc != 3) {
> +    Print(L"CapsuleApp: Invalid Parameter.\n");
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  IsSystemFmp = FALSE;
> +  if (StrCmp(Argv[1], L"-DS") == 0) {
> +    IsSystemFmp = TRUE;
> +  }
> +
> +  CapsuleName = Argv[2];
> +  Status = ReadFileToBuffer(CapsuleName, &FileSize, &Buffer);
> +  if (EFI_ERROR(Status)) {
> +    Print(L"CapsuleApp: Capsule (%s) is not found.\n", CapsuleName);
> +    goto Done;
> +  }
> +
> +  CapsuleHeader = Buffer;
> +  if (CompareGuid(&CapsuleHeader->CapsuleGuid, &gWindowsUxCapsuleGuid)) {
> +    DumpUxCapsule(CapsuleHeader);
> +    Status = EFI_SUCCESS;
> +    goto Done;
> +  }
> +
> +  if (CompareGuid(&CapsuleHeader->CapsuleGuid, &gEfiFmpCapsuleGuid)) {
> +    DumpFmpCapsule(CapsuleHeader, IsSystemFmp);
> +  }
> +  if (IsNestedFmpCapsule(CapsuleHeader)) {
> +    Print(L"[NestedCapusule]\n");
> +    Print(L"CapsuleHeader:\n");
> +    Print(L"  CapsuleGuid      - %g\n", &CapsuleHeader->CapsuleGuid);
> +    Print(L"  HeaderSize       - 0x%x\n", CapsuleHeader->HeaderSize);
> +    Print(L"  Flags            - 0x%x\n", CapsuleHeader->Flags);
> +    Print(L"  CapsuleImageSize - 0x%x\n", CapsuleHeader->CapsuleImageSize);
> +    DumpFmpCapsule((EFI_CAPSULE_HEADER *)((UINTN)CapsuleHeader + CapsuleHeader-
> >HeaderSize), IsSystemFmp);
> +  }
> +
> +Done:
> +  FreePool(Buffer);
> +  return Status;
> +}
> +
> +/**
> +  Dump capsule status variable.
> +
> +  @retval EFI_SUCCESS            The capsule status variable is dumped.
> +  @retval EFI_UNSUPPORTED        Input parameter is not valid.
> +**/
> +EFI_STATUS
> +DmpCapsuleStatusVariable(
> +  VOID
> +  )
> +{
> +  EFI_STATUS                          Status;
> +  UINT32                              Index;
> +  CHAR16                              CapsuleVarName[20];
> +  CHAR16                              *TempVarName;
> +  EFI_CAPSULE_RESULT_VARIABLE_HEADER  *CapsuleResult;
> +  EFI_CAPSULE_RESULT_VARIABLE_FMP     *CapsuleResultFmp;
> +  UINTN                               CapsuleFileNameSize;
> +  CHAR16                              CapsuleIndexData[12];
> +  CHAR16                              *CapsuleIndex;
> +
> +  Status = GetVariable2(
> +             L"CapsuleMax",
> +             &gEfiCapsuleReportGuid,
> +             (VOID **)&CapsuleIndex,
> +             NULL
> +             );
> +  if (!EFI_ERROR(Status)) {
> +    CopyMem(CapsuleIndexData, CapsuleIndex, 11 * sizeof(CHAR16));
> +    CapsuleIndexData[11] = 0;
> +    Print(L"CapsuleMax - %s\n", CapsuleIndexData);
> +    FreePool(CapsuleIndex);
> +  }
> +  Status = GetVariable2(
> +             L"CapsuleLast",
> +             &gEfiCapsuleReportGuid,
> +             (VOID **)&CapsuleIndex,
> +             NULL
> +             );
> +  if (!EFI_ERROR(Status)) {
> +    CopyMem(CapsuleIndexData, CapsuleIndex, 11 * sizeof(CHAR16));
> +    CapsuleIndexData[11] = 0;
> +    Print(L"CapsuleLast - %s\n", CapsuleIndexData);
> +    FreePool(CapsuleIndex);
> +  }
> +
> +
> +  StrCpyS (CapsuleVarName, sizeof(CapsuleVarName)/sizeof(CapsuleVarName[0]),
> L"Capsule");
> +  TempVarName = CapsuleVarName + StrLen (CapsuleVarName);
> +  Index = 0;
> +
> +  while (TRUE) {
> +    UnicodeSPrint (TempVarName, 5 * sizeof(CHAR16), L"%04x", Index);
> +
> +    Status = GetVariable2 (
> +               CapsuleVarName,
> +               &gEfiCapsuleReportGuid,
> +               (VOID **) &CapsuleResult,
> +               NULL
> +               );
> +    if (Status == EFI_NOT_FOUND) {
> +      break;
> +    } else if (EFI_ERROR(Status)) {
> +      continue;
> +    }
> +
> +    //
> +    // display capsule process status
> +    //
> +    if (CapsuleResult->VariableTotalSize >=
> sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER)) {
> +      Print (L"CapsuleName: %s\n", CapsuleVarName);
> +      Print (L"  Capsule Guid: %g\n", &CapsuleResult->CapsuleGuid);
> +      Print (L"  Capsule ProcessedTime: %t\n", &CapsuleResult->CapsuleProcessed);
> +      Print (L"  Capsule Status: %r\n", CapsuleResult->CapsuleStatus);
> +    }
> +
> +    if (CompareGuid(&CapsuleResult->CapsuleGuid, &gEfiFmpCapsuleGuid)) {
> +      if (CapsuleResult->VariableTotalSize >=
> sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER) + sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP)) {
> +        CapsuleResultFmp = (EFI_CAPSULE_RESULT_VARIABLE_FMP *)(CapsuleResult + 1);
> +        Print(L"  Capsule FMP Version: 0x%x\n", CapsuleResultFmp->Version);
> +        Print(L"  Capsule FMP PayloadIndex: 0x%x\n", CapsuleResultFmp->PayloadIndex);
> +        Print(L"  Capsule FMP UpdateImageIndex: 0x%x\n", CapsuleResultFmp-
> >UpdateImageIndex);
> +        Print(L"  Capsule FMP UpdateImageTypeId: %g\n", &CapsuleResultFmp-
> >UpdateImageTypeId);
> +        if (CapsuleResult->VariableTotalSize >
> sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER) + sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP)) {
> +          Print(L"  Capsule FMP CapsuleFileName: %s\n", (CapsuleResultFmp + 1));
> +          CapsuleFileNameSize = StrSize((CHAR16 *)(CapsuleResultFmp + 1));
> +          if (CapsuleResult->VariableTotalSize >
> sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER) + sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP) +
> CapsuleFileNameSize) {
> +            Print(L"  Capsule FMP CapsuleTarget: %s\n", (UINT8 *)(CapsuleResultFmp +
> 1) + CapsuleFileNameSize);
> +          }
> +        }
> +      }
> +    }
> +
> +    FreePool(CapsuleResult);
> +
> +    Index++;
> +    if (Index > 0xFFFF) {
> +      break;
> +    }
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +CHAR8 *mFwTypeString[] = {
> +  "Unknown",
> +  "SystemFirmware",
> +  "DeviceFirmware",
> +  "UefiDriver",
> +};
> +
> +CHAR8 *mLastAttemptStatusString[] = {
> +  "Success",
> +  "Error: Unsuccessful",
> +  "Error: Insufficient Resources",
> +  "Error: Incorrect Version",
> +  "Error: Invalid Format",
> +  "Error: Auth Error",
> +  "Error: Power Event AC",
> +  "Error: Power Event Battery",
> +};
> +
> +/**
> +  Convert FwType to a string.
> +
> +  @param FwType  FwType in ESRT
> +
> +  @return a string for FwType.
> +**/
> +CHAR8 *
> +FwTypeToString(
> +  IN UINT32 FwType
> +  )
> +{
> +  if (FwType < sizeof(mFwTypeString) / sizeof(mFwTypeString[0])) {
> +    return mFwTypeString[FwType];
> +  } else {
> +    return "Invalid";
> +  }
> +}
> +
> +/**
> +  Convert LastAttemptStatus to a string.
> +
> +  @param LastAttemptStatus  LastAttemptStatus in FMP or ESRT
> +
> +  @return a string for LastAttemptStatus.
> +**/
> +CHAR8 *
> +LastAttemptStatusToString(
> +  IN UINT32 LastAttemptStatus
> +  )
> +{
> +  if (LastAttemptStatus < sizeof(mLastAttemptStatusString) /
> sizeof(mLastAttemptStatusString[0])) {
> +    return mLastAttemptStatusString[LastAttemptStatus];
> +  } else {
> +    return "Error: Unknown";
> +  }
> +}
> +
> +/**
> +  Dump ESRT entry.
> +
> +  @param EsrtEntry  ESRT entry
> +**/
> +VOID
> +DumpEsrtEntry(
> +  IN EFI_SYSTEM_RESOURCE_ENTRY  *EsrtEntry
> +  )
> +{
> +  Print(L"  FwClass                  - %g\n", &EsrtEntry->FwClass);
> +  Print(L"  FwType                   - 0x%x (%a)\n", EsrtEntry->FwType,
> FwTypeToString(EsrtEntry->FwType));
> +  Print(L"  FwVersion                - 0x%x\n", EsrtEntry->FwVersion);
> +  Print(L"  LowestSupportedFwVersion - 0x%x\n", EsrtEntry->LowestSupportedFwVersion);
> +  Print(L"  CapsuleFlags             - 0x%x\n", EsrtEntry->CapsuleFlags);
> +  Print(L"    PERSIST_ACROSS_RESET   - 0x%x\n", EsrtEntry->CapsuleFlags &
> CAPSULE_FLAGS_PERSIST_ACROSS_RESET);
> +  Print(L"    POPULATE_SYSTEM_TABLE  - 0x%x\n", EsrtEntry->CapsuleFlags &
> CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE);
> +  Print(L"    INITIATE_RESET         - 0x%x\n", EsrtEntry->CapsuleFlags &
> CAPSULE_FLAGS_INITIATE_RESET);
> +  Print(L"  LastAttemptVersion       - 0x%x\n", EsrtEntry->LastAttemptVersion);
> +  Print(L"  LastAttemptStatus        - 0x%x (%a)\n", EsrtEntry->LastAttemptStatus,
> LastAttemptStatusToString(EsrtEntry->LastAttemptStatus));
> +}
> +
> +/**
> +  Dump ESRT table.
> +
> +  @param Esrt  ESRT table
> +**/
> +VOID
> +DumpEsrt(
> +  IN EFI_SYSTEM_RESOURCE_TABLE  *Esrt
> +  )
> +{
> +  UINTN                      Index;
> +  EFI_SYSTEM_RESOURCE_ENTRY  *EsrtEntry;
> +
> +  Print(L"EFI_SYSTEM_RESOURCE_TABLE:\n");
> +  Print(L"FwResourceCount    - 0x%x\n", Esrt->FwResourceCount);
> +  Print(L"FwResourceCountMax - 0x%x\n", Esrt->FwResourceCountMax);
> +  Print(L"FwResourceVersion  - 0x%lx\n", Esrt->FwResourceVersion);
> +
> +  EsrtEntry = (VOID *)(Esrt + 1);
> +  for (Index = 0; Index < Esrt->FwResourceCount; Index++) {
> +    Print(L"EFI_SYSTEM_RESOURCE_ENTRY (%d):\n", Index);
> +    DumpEsrtEntry(EsrtEntry);
> +    EsrtEntry++;
> +  }
> +}
> +
> +/**
> +  Dump ESRT info.
> +**/
> +VOID
> +DumpEsrtData (
> +  VOID
> +  )
> +{
> +  EFI_STATUS                 Status;
> +  EFI_SYSTEM_RESOURCE_TABLE  *Esrt;
> +
> +  Print(L"##############\n");
> +  Print(L"# ESRT TABLE #\n");
> +  Print(L"##############\n");
> +
> +  Status = EfiGetSystemConfigurationTable (&gEfiSystemResourceTableGuid, (VOID
> **)&Esrt);
> +  if (EFI_ERROR(Status)) {
> +    Print(L"ESRT - %r\n", Status);
> +    return;
> +  }
> +  DumpEsrt(Esrt);
> +  Print(L"\n");
> +}
> +
> +/**
> +  Dump FMP information.
> +
> +  @param ImageInfoSize       The size of ImageInfo, in bytes.
> +  @param ImageInfo           A pointer to EFI_FIRMWARE_IMAGE_DESCRIPTOR.
> +  @param DescriptorVersion   The version of EFI_FIRMWARE_IMAGE_DESCRIPTOR.
> +  @param DescriptorCount     The count of EFI_FIRMWARE_IMAGE_DESCRIPTOR.
> +  @param DescriptorSize      The size of an individual EFI_FIRMWARE_IMAGE_DESCRIPTOR,
> in bytes.
> +  @param PackageVersion      The version of package.
> +  @param PackageVersionName  The version name of package.
> +**/
> +VOID
> +DumpFmpImageInfo(
> +  IN UINTN                           ImageInfoSize,
> +  IN EFI_FIRMWARE_IMAGE_DESCRIPTOR   *ImageInfo,
> +  IN UINT32                          DescriptorVersion,
> +  IN UINT8                           DescriptorCount,
> +  IN UINTN                           DescriptorSize,
> +  IN UINT32                          PackageVersion,
> +  IN CHAR16                          *PackageVersionName
> +  )
> +{
> +  EFI_FIRMWARE_IMAGE_DESCRIPTOR                 *CurrentImageInfo;
> +  UINTN                                         Index;
> +
> +  Print(L"  DescriptorVersion  - 0x%x\n", DescriptorVersion);
> +  Print(L"  DescriptorCount    - 0x%x\n", DescriptorCount);
> +  Print(L"  DescriptorSize     - 0x%x\n", DescriptorSize);
> +  Print(L"  PackageVersion     - 0x%x\n", PackageVersion);
> +  Print(L"  PackageVersionName - \"%s\"\n", PackageVersionName);
> +  CurrentImageInfo = ImageInfo;
> +  for (Index = 0; Index < DescriptorCount; Index++) {
> +    Print(L"  ImageDescriptor (%d)\n", Index);
> +    Print(L"    ImageIndex                  - 0x%x\n", CurrentImageInfo->ImageIndex);
> +    Print(L"    ImageTypeId                 - %g\n", &CurrentImageInfo->ImageTypeId);
> +    Print(L"    ImageId                     - 0x%lx\n", CurrentImageInfo->ImageId);
> +    Print(L"    ImageIdName                 - \"%s\"\n", CurrentImageInfo-
> >ImageIdName);
> +    Print(L"    Version                     - 0x%x\n", CurrentImageInfo->Version);
> +    Print(L"    VersionName                 - \"%s\"\n", CurrentImageInfo-
> >VersionName);
> +    Print(L"    Size                        - 0x%x\n", CurrentImageInfo->Size);
> +    Print(L"    AttributesSupported         - 0x%lx\n", CurrentImageInfo-
> >AttributesSupported);
> +    Print(L"      IMAGE_UPDATABLE           - 0x%lx\n", CurrentImageInfo-
> >AttributesSupported & IMAGE_ATTRIBUTE_IMAGE_UPDATABLE);
> +    Print(L"      RESET_REQUIRED            - 0x%lx\n", CurrentImageInfo-
> >AttributesSupported & IMAGE_ATTRIBUTE_RESET_REQUIRED);
> +    Print(L"      AUTHENTICATION_REQUIRED   - 0x%lx\n", CurrentImageInfo-
> >AttributesSupported & IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);
> +    Print(L"      IN_USE                    - 0x%lx\n", CurrentImageInfo-
> >AttributesSupported & IMAGE_ATTRIBUTE_IN_USE);
> +    Print(L"      UEFI_IMAGE                - 0x%lx\n", CurrentImageInfo-
> >AttributesSupported & IMAGE_ATTRIBUTE_UEFI_IMAGE);
> +    Print(L"    AttributesSetting           - 0x%lx\n", CurrentImageInfo-
> >AttributesSetting);
> +    Print(L"      IMAGE_UPDATABLE           - 0x%lx\n", CurrentImageInfo-
> >AttributesSetting & IMAGE_ATTRIBUTE_IMAGE_UPDATABLE);
> +    Print(L"      RESET_REQUIRED            - 0x%lx\n", CurrentImageInfo-
> >AttributesSetting & IMAGE_ATTRIBUTE_RESET_REQUIRED);
> +    Print(L"      AUTHENTICATION_REQUIRED   - 0x%lx\n", CurrentImageInfo-
> >AttributesSetting & IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);
> +    Print(L"      IN_USE                    - 0x%lx\n", CurrentImageInfo-
> >AttributesSetting & IMAGE_ATTRIBUTE_IN_USE);
> +    Print(L"      UEFI_IMAGE                - 0x%lx\n", CurrentImageInfo-
> >AttributesSetting & IMAGE_ATTRIBUTE_UEFI_IMAGE);
> +    Print(L"    Compatibilities             - 0x%lx\n", CurrentImageInfo-
> >Compatibilities);
> +    Print(L"      COMPATIB_CHECK_SUPPORTED  - 0x%lx\n", CurrentImageInfo-
> >Compatibilities & IMAGE_COMPATIBILITY_CHECK_SUPPORTED);
> +    if (DescriptorVersion > 1) {
> +      Print(L"    LowestSupportedImageVersion - 0x%x\n", CurrentImageInfo-
> >LowestSupportedImageVersion);
> +      if (DescriptorVersion > 2) {
> +        Print(L"    LastAttemptVersion          - 0x%x\n", CurrentImageInfo-
> >LastAttemptVersion);
> +        Print(L"    LastAttemptStatus           - 0x%x (%a)\n", CurrentImageInfo-
> >LastAttemptStatus, LastAttemptStatusToString(CurrentImageInfo->LastAttemptStatus));
> +        Print(L"    HardwareInstance            - 0x%lx\n", CurrentImageInfo-
> >HardwareInstance);
> +      }
> +    }
> +    //
> +    // Use DescriptorSize to move ImageInfo Pointer to stay compatible with different
> ImageInfo version
> +    //
> +    CurrentImageInfo = (EFI_FIRMWARE_IMAGE_DESCRIPTOR *)((UINT8 *)CurrentImageInfo +
> DescriptorSize);
> +  }
> +}
> +
> +/**
> +  Dump FMP package information.
> +
> +  @param PackageVersion             The version of package.
> +  @param PackageVersionName         The version name of package.
> +  @param PackageVersionNameMaxLen   The maximum length of PackageVersionName.
> +  @param AttributesSupported        Package attributes that are supported by this
> device.
> +  @param AttributesSetting          Package attributes.
> +**/
> +VOID
> +DumpFmpPackageInfo(
> +  IN UINT32                           PackageVersion,
> +  IN CHAR16                           *PackageVersionName,
> +  IN UINT32                           PackageVersionNameMaxLen,
> +  IN UINT64                           AttributesSupported,
> +  IN UINT64                           AttributesSetting
> +  )
> +{
> +  Print(L"  PackageVersion              - 0x%x\n", PackageVersion);
> +  Print(L"  PackageVersionName          - \"%s\"\n", PackageVersionName);
> +  Print(L"  PackageVersionNameMaxLen    - 0x%x\n", PackageVersionNameMaxLen);
> +  Print(L"  AttributesSupported         - 0x%lx\n", AttributesSupported);
> +  Print(L"    IMAGE_UPDATABLE           - 0x%lx\n", AttributesSupported &
> IMAGE_ATTRIBUTE_IMAGE_UPDATABLE);
> +  Print(L"    RESET_REQUIRED            - 0x%lx\n", AttributesSupported &
> IMAGE_ATTRIBUTE_RESET_REQUIRED);
> +  Print(L"    AUTHENTICATION_REQUIRED   - 0x%lx\n", AttributesSupported &
> IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);
> +  Print(L"  AttributesSetting           - 0x%lx\n", AttributesSetting);
> +  Print(L"    IMAGE_UPDATABLE           - 0x%lx\n", AttributesSetting &
> IMAGE_ATTRIBUTE_IMAGE_UPDATABLE);
> +  Print(L"    RESET_REQUIRED            - 0x%lx\n", AttributesSetting &
> IMAGE_ATTRIBUTE_RESET_REQUIRED);
> +  Print(L"    AUTHENTICATION_REQUIRED   - 0x%lx\n", AttributesSetting &
> IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);
> +}
> +
> +/**
> +  Dump FMP protocol info.
> +**/
> +VOID
> +DumpFmpData (
> +  VOID
> +  )
> +{
> +  EFI_STATUS                                    Status;
> +  EFI_FIRMWARE_MANAGEMENT_PROTOCOL              *Fmp;
> +  EFI_HANDLE                                    *HandleBuffer;
> +  UINTN                                         NumberOfHandles;
> +  UINTN                                         Index;
> +  EFI_FIRMWARE_IMAGE_DESCRIPTOR                 *FmpImageInfoBuf;
> +  UINTN                                         ImageInfoSize;
> +  UINT32                                        FmpImageInfoDescriptorVer;
> +  UINT8                                         FmpImageInfoCount;
> +  UINTN                                         DescriptorSize;
> +  UINT32                                        PackageVersion;
> +  CHAR16                                        *PackageVersionName;
> +  UINT32                                        PackageVersionNameMaxLen;
> +  UINT64                                        AttributesSupported;
> +  UINT64                                        AttributesSetting;
> +
> +  Print(L"############\n");
> +  Print(L"# FMP DATA #\n");
> +  Print(L"############\n");
> +  Status = gBS->LocateHandleBuffer (
> +                  ByProtocol,
> +                  &gEfiFirmwareManagementProtocolGuid,
> +                  NULL,
> +                  &NumberOfHandles,
> +                  &HandleBuffer
> +                  );
> +  if (EFI_ERROR(Status)) {
> +    Print(L"FMP protocol - %r\n", EFI_NOT_FOUND);
> +    return;
> +  }
> +
> +  for (Index = 0; Index < NumberOfHandles; Index++) {
> +    Status = gBS->HandleProtocol(
> +                    HandleBuffer[Index],
> +                    &gEfiFirmwareManagementProtocolGuid,
> +                    (VOID **)&Fmp
> +                    );
> +    if (EFI_ERROR(Status)) {
> +      continue;
> +    }
> +
> +    ImageInfoSize = 0;
> +    Status = Fmp->GetImageInfo (
> +                    Fmp,
> +                    &ImageInfoSize,
> +                    NULL,
> +                    NULL,
> +                    NULL,
> +                    NULL,
> +                    NULL,
> +                    NULL
> +                    );
> +    if (Status != EFI_BUFFER_TOO_SMALL) {
> +      continue;
> +    }
> +
> +    FmpImageInfoBuf = NULL;
> +    FmpImageInfoBuf = AllocateZeroPool (ImageInfoSize);
> +    if (FmpImageInfoBuf == NULL) {
> +      Status = EFI_OUT_OF_RESOURCES;
> +      goto EXIT;
> +    }
> +
> +    PackageVersionName = NULL;
> +    Status = Fmp->GetImageInfo (
> +                    Fmp,
> +                    &ImageInfoSize,               // ImageInfoSize
> +                    FmpImageInfoBuf,              // ImageInfo
> +                    &FmpImageInfoDescriptorVer,   // DescriptorVersion
> +                    &FmpImageInfoCount,           // DescriptorCount
> +                    &DescriptorSize,              // DescriptorSize
> +                    &PackageVersion,              // PackageVersion
> +                    &PackageVersionName           // PackageVersionName
> +                    );
> +
> +    //
> +    // If FMP GetInformation interface failed, skip this resource
> +    //
> +    if (EFI_ERROR(Status)) {
> +      Print(L"FMP (%d) ImageInfo - %r\n", Index, Status);
> +      FreePool(FmpImageInfoBuf);
> +      continue;
> +    }
> +
> +    Print(L"FMP (%d) ImageInfo:\n", Index);
> +    DumpFmpImageInfo(
> +      ImageInfoSize,               // ImageInfoSize
> +      FmpImageInfoBuf,             // ImageInfo
> +      FmpImageInfoDescriptorVer,   // DescriptorVersion
> +      FmpImageInfoCount,           // DescriptorCount
> +      DescriptorSize,              // DescriptorSize
> +      PackageVersion,              // PackageVersion
> +      PackageVersionName           // PackageVersionName
> +      );
> +
> +    if (PackageVersionName != NULL) {
> +      FreePool(PackageVersionName);
> +    }
> +    FreePool(FmpImageInfoBuf);
> +
> +    //
> +    // Get package info
> +    //
> +    PackageVersionName = NULL;
> +    Status = Fmp->GetPackageInfo (
> +                    Fmp,
> +                    &PackageVersion,              // PackageVersion
> +                    &PackageVersionName,          // PackageVersionName
> +                    &PackageVersionNameMaxLen,    // PackageVersionNameMaxLen
> +                    &AttributesSupported,         // AttributesSupported
> +                    &AttributesSetting            // AttributesSetting
> +                    );
> +    if (EFI_ERROR(Status)) {
> +      Print(L"FMP (%d) PackageInfo - %r\n", Index, Status);
> +    } else {
> +      Print(L"FMP (%d) ImageInfo:\n", Index);
> +      DumpFmpPackageInfo(
> +        PackageVersion,              // PackageVersion
> +        PackageVersionName,          // PackageVersionName
> +        PackageVersionNameMaxLen,    // PackageVersionNameMaxLen
> +        AttributesSupported,         // AttributesSupported
> +        AttributesSetting            // AttributesSetting
> +        );
> +
> +      if (PackageVersionName != NULL) {
> +        FreePool(PackageVersionName);
> +      }
> +    }
> +  }
> +  Print(L"\n");
> +
> +EXIT:
> +  FreePool(HandleBuffer);
> +}
> --
> 2.7.4.windows.1
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>
https://lists.01.org/mailman/listinfo/edk2-devel

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

* Re: [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application.
  2016-10-11  8:28                     ` Ni, Ruiyu
  2016-10-11  8:46                       ` Yao, Jiewen
@ 2016-10-11 14:44                       ` Yao, Jiewen
  2016-10-12 21:04                         ` Carsey, Jaben
  1 sibling, 1 reply; 83+ messages in thread
From: Yao, Jiewen @ 2016-10-11 14:44 UTC (permalink / raw)
  To: Ni, Ruiyu, Carsey, Jaben, Rothman, Michael A, Kinney, Michael D,
	'edk2-devel@lists.01.org'
  Cc: Tian, Feng, Zhang, Chao B, Gao, Liming, Zeng, Star

Yes, I think that is a very good idea.

Shell spec defines EFI_SHELL_PROTOCOL, EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL, EFI_SHELL_PARAMETERS_PROTOCOL.
These should be treated as industry stand and we can move these 3 to MdePkg.

SHELL_ENVIRONMENT_2_PROTOCOL and SHELL_INTERFACE_PROTOCOL should be still in ShellPkg, since it is not standard.

Thank you
Yao Jiewen


From: Ni, Ruiyu
Sent: Tuesday, October 11, 2016 4:28 PM
To: Carsey, Jaben <jaben.carsey@intel.com>; Rothman, Michael A <michael.a.rothman@intel.com>; Yao, Jiewen <jiewen.yao@intel.com>; Kinney, Michael D <michael.d.kinney@intel.com>; 'edk2-devel@lists.01.org' <edk2-devel@lists.01.org>
Cc: Tian, Feng <feng.tian@intel.com>; Zhang, Chao B <chao.b.zhang@intel.com>; Gao, Liming <liming.gao@intel.com>; Zeng, Star <star.zeng@intel.com>
Subject: RE: [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application.

Jaben,
The reason I propose to move the Shell protocol definitions to MdePkg is that all applications that wants to use the ARGV can use the ShellParameter protocol, without depending on ShellPkg.

Thanks/Ray

From: Ni, Ruiyu
Sent: Tuesday, October 11, 2016 4:08 PM
To: Carsey, Jaben <jaben.carsey@intel.com<mailto:jaben.carsey@intel.com>>; Rothman, Michael A <michael.a.rothman@intel.com<mailto:michael.a.rothman@intel.com>>; Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>; edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>
Cc: Tian, Feng <feng.tian@intel.com<mailto:feng.tian@intel.com>>; Zhang, Chao B <chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com>>; Gao, Liming <liming.gao@intel.com<mailto:liming.gao@intel.com>>; Zeng, Star <star.zeng@intel.com<mailto:star.zeng@intel.com>>
Subject: RE: [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application.

Jaben,
How about moving the contents in ShellPkg\Include\Protocol\ to MdePkg\Include\Protocol\?
All industry standard protocols are defined in MdePkg, except the Shell related protocols.

Thanks/Ray

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

* Re: [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application.
  2016-10-11 14:44                       ` Yao, Jiewen
@ 2016-10-12 21:04                         ` Carsey, Jaben
  2016-10-13  1:07                           ` Yao, Jiewen
  0 siblings, 1 reply; 83+ messages in thread
From: Carsey, Jaben @ 2016-10-12 21:04 UTC (permalink / raw)
  To: Yao, Jiewen, Ni, Ruiyu, Rothman, Michael A, Kinney, Michael D,
	'edk2-devel@lists.01.org'
  Cc: Tian, Feng, Zhang, Chao B, Gao, Liming, Zeng, Star, Carsey, Jaben

I agree.

We should move the 3 protocols from the UEFI Shell Specification from ShellPkg to MdePkg.

I think that this is a non-backwards-compatible-change and will require a new GUID in ShellPkg.

-Jaben

From: Yao, Jiewen
Sent: Tuesday, October 11, 2016 7:45 AM
To: Ni, Ruiyu <ruiyu.ni@intel.com>; Carsey, Jaben <jaben.carsey@intel.com>; Rothman, Michael A <michael.a.rothman@intel.com>; Kinney, Michael D <michael.d.kinney@intel.com>; 'edk2-devel@lists.01.org' <edk2-devel@lists.01.org>
Cc: Tian, Feng <feng.tian@intel.com>; Zhang, Chao B <chao.b.zhang@intel.com>; Gao, Liming <liming.gao@intel.com>; Zeng, Star <star.zeng@intel.com>
Subject: RE: [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application.
Importance: High

Yes, I think that is a very good idea.

Shell spec defines EFI_SHELL_PROTOCOL, EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL, EFI_SHELL_PARAMETERS_PROTOCOL.
These should be treated as industry stand and we can move these 3 to MdePkg.

SHELL_ENVIRONMENT_2_PROTOCOL and SHELL_INTERFACE_PROTOCOL should be still in ShellPkg, since it is not standard.

Thank you
Yao Jiewen


From: Ni, Ruiyu
Sent: Tuesday, October 11, 2016 4:28 PM
To: Carsey, Jaben <jaben.carsey@intel.com<mailto:jaben.carsey@intel.com>>; Rothman, Michael A <michael.a.rothman@intel.com<mailto:michael.a.rothman@intel.com>>; Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>; 'edk2-devel@lists.01.org' <edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>>
Cc: Tian, Feng <feng.tian@intel.com<mailto:feng.tian@intel.com>>; Zhang, Chao B <chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com>>; Gao, Liming <liming.gao@intel.com<mailto:liming.gao@intel.com>>; Zeng, Star <star.zeng@intel.com<mailto:star.zeng@intel.com>>
Subject: RE: [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application.

Jaben,
The reason I propose to move the Shell protocol definitions to MdePkg is that all applications that wants to use the ARGV can use the ShellParameter protocol, without depending on ShellPkg.

Thanks/Ray

From: Ni, Ruiyu
Sent: Tuesday, October 11, 2016 4:08 PM
To: Carsey, Jaben <jaben.carsey@intel.com<mailto:jaben.carsey@intel.com>>; Rothman, Michael A <michael.a.rothman@intel.com<mailto:michael.a.rothman@intel.com>>; Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>; edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>
Cc: Tian, Feng <feng.tian@intel.com<mailto:feng.tian@intel.com>>; Zhang, Chao B <chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com>>; Gao, Liming <liming.gao@intel.com<mailto:liming.gao@intel.com>>; Zeng, Star <star.zeng@intel.com<mailto:star.zeng@intel.com>>
Subject: RE: [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application.

Jaben,
How about moving the contents in ShellPkg\Include\Protocol\ to MdePkg\Include\Protocol\?
All industry standard protocols are defined in MdePkg, except the Shell related protocols.

Thanks/Ray

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

* Re: [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application.
  2016-10-12 21:04                         ` Carsey, Jaben
@ 2016-10-13  1:07                           ` Yao, Jiewen
  0 siblings, 0 replies; 83+ messages in thread
From: Yao, Jiewen @ 2016-10-13  1:07 UTC (permalink / raw)
  To: Carsey, Jaben, Ni, Ruiyu, Rothman, Michael A, Kinney, Michael D,
	'edk2-devel@lists.01.org'
  Cc: Tian, Feng, Zhang, Chao B, Gao, Liming, Zeng, Star

Sounds good! Thanks to confirm that.

From: Carsey, Jaben
Sent: Thursday, October 13, 2016 5:04 AM
To: Yao, Jiewen <jiewen.yao@intel.com>; Ni, Ruiyu <ruiyu.ni@intel.com>; Rothman, Michael A <michael.a.rothman@intel.com>; Kinney, Michael D <michael.d.kinney@intel.com>; 'edk2-devel@lists.01.org' <edk2-devel@lists.01.org>
Cc: Tian, Feng <feng.tian@intel.com>; Zhang, Chao B <chao.b.zhang@intel.com>; Gao, Liming <liming.gao@intel.com>; Zeng, Star <star.zeng@intel.com>; Carsey, Jaben <jaben.carsey@intel.com>
Subject: RE: [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application.

I agree.

We should move the 3 protocols from the UEFI Shell Specification from ShellPkg to MdePkg.

I think that this is a non-backwards-compatible-change and will require a new GUID in ShellPkg.

-Jaben

From: Yao, Jiewen
Sent: Tuesday, October 11, 2016 7:45 AM
To: Ni, Ruiyu <ruiyu.ni@intel.com<mailto:ruiyu.ni@intel.com>>; Carsey, Jaben <jaben.carsey@intel.com<mailto:jaben.carsey@intel.com>>; Rothman, Michael A <michael.a.rothman@intel.com<mailto:michael.a.rothman@intel.com>>; Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>; 'edk2-devel@lists.01.org' <edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>>
Cc: Tian, Feng <feng.tian@intel.com<mailto:feng.tian@intel.com>>; Zhang, Chao B <chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com>>; Gao, Liming <liming.gao@intel.com<mailto:liming.gao@intel.com>>; Zeng, Star <star.zeng@intel.com<mailto:star.zeng@intel.com>>
Subject: RE: [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application.
Importance: High

Yes, I think that is a very good idea.

Shell spec defines EFI_SHELL_PROTOCOL, EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL, EFI_SHELL_PARAMETERS_PROTOCOL.
These should be treated as industry stand and we can move these 3 to MdePkg.

SHELL_ENVIRONMENT_2_PROTOCOL and SHELL_INTERFACE_PROTOCOL should be still in ShellPkg, since it is not standard.

Thank you
Yao Jiewen


From: Ni, Ruiyu
Sent: Tuesday, October 11, 2016 4:28 PM
To: Carsey, Jaben <jaben.carsey@intel.com<mailto:jaben.carsey@intel.com>>; Rothman, Michael A <michael.a.rothman@intel.com<mailto:michael.a.rothman@intel.com>>; Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>; 'edk2-devel@lists.01.org' <edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>>
Cc: Tian, Feng <feng.tian@intel.com<mailto:feng.tian@intel.com>>; Zhang, Chao B <chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com>>; Gao, Liming <liming.gao@intel.com<mailto:liming.gao@intel.com>>; Zeng, Star <star.zeng@intel.com<mailto:star.zeng@intel.com>>
Subject: RE: [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application.

Jaben,
The reason I propose to move the Shell protocol definitions to MdePkg is that all applications that wants to use the ARGV can use the ShellParameter protocol, without depending on ShellPkg.

Thanks/Ray

From: Ni, Ruiyu
Sent: Tuesday, October 11, 2016 4:08 PM
To: Carsey, Jaben <jaben.carsey@intel.com<mailto:jaben.carsey@intel.com>>; Rothman, Michael A <michael.a.rothman@intel.com<mailto:michael.a.rothman@intel.com>>; Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>; edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>
Cc: Tian, Feng <feng.tian@intel.com<mailto:feng.tian@intel.com>>; Zhang, Chao B <chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com>>; Gao, Liming <liming.gao@intel.com<mailto:liming.gao@intel.com>>; Zeng, Star <star.zeng@intel.com<mailto:star.zeng@intel.com>>
Subject: RE: [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application.

Jaben,
How about moving the contents in ShellPkg\Include\Protocol\ to MdePkg\Include\Protocol\?
All industry standard protocols are defined in MdePkg, except the Shell related protocols.

Thanks/Ray

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

end of thread, other threads:[~2016-10-13  1:08 UTC | newest]

Thread overview: 83+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-09-21  6:44 [PATCH 00/45] Add capsule update and recovery sample Jiewen Yao
2016-09-21  6:44 ` [PATCH 01/45] MdeModulePkg/Include: Add EDKII system FMP capsule header Jiewen Yao
2016-09-21  6:44 ` [PATCH 02/45] MdeModulePkg/Include: Add EdkiiSystemCapsuleLib definition Jiewen Yao
2016-09-21  6:44 ` [PATCH 03/45] MdeModulePkg/Include: Add FmpAuthenticationLib header Jiewen Yao
2016-09-21  6:44 ` [PATCH 04/45] MdeModulePkg/Include: Add IniParsingLib header Jiewen Yao
2016-09-29  6:53   ` Ni, Ruiyu
2016-09-29  7:10     ` Yao, Jiewen
2016-09-21  6:44 ` [PATCH 05/45] MdeModulePkg/Include: Add PlatformFlashAccessLib header Jiewen Yao
2016-09-21  6:44 ` [PATCH 06/45] MdeModulePkg/CapsuleLib: Add ProcessCapsules() API Jiewen Yao
2016-09-21  6:44 ` [PATCH 07/45] MdeModulePkg/MdeModulePkg.dec: Add capsule related definition Jiewen Yao
2016-09-21  6:44 ` [PATCH 08/45] MdeModulePkg/IniParsingLib: Add InitParsingLib instance Jiewen Yao
2016-09-21  6:44 ` [PATCH 09/45] MdeModulePkg/FmpAuthenticationLib: Add FmpAuthenticationLib instance Jiewen Yao
2016-09-21  6:44 ` [PATCH 10/45] MdeModulePkg/DxeCapsuleLibFmp: Add DxeCapsuleLibFmp instance Jiewen Yao
2016-09-21  6:44 ` [PATCH 11/45] MdeModulePkg/DxeCapsuleLibNull: Add ProcessCapsules() interface Jiewen Yao
2016-09-21  6:44 ` [PATCH 12/45] MdeModulePkg/EdkiiSystemCapsuleLib: Add EdkiiSystemCapsuleLib instance Jiewen Yao
2016-09-21  6:44 ` [PATCH 13/45] MdeModulePkg/PlatformFlashAccessLib: Add NULL PlatformFlashAccessLib Jiewen Yao
2016-09-21  6:44 ` [PATCH 14/45] MdeModulePkg/Esrt: Add ESRT_FW_TYPE_SYSTEMFIRMWARE check Jiewen Yao
2016-09-21  6:44 ` [PATCH 15/45] MdeModulePkg/SystemBiosUpdate: Add SystemBiosUpdate component Jiewen Yao
2016-09-21  6:44 ` [PATCH 16/45] MdeModulePkg/RecoveryModuleLoadPei: Add RecoveryModuleLoadPei Jiewen Yao
2016-09-21  6:44 ` [PATCH 17/45] MdeModulePkg/CapsuleApp: Add CapsuleApp application Jiewen Yao
2016-09-29  1:06   ` Kinney, Michael D
2016-09-29  2:37     ` Yao, Jiewen
2016-09-29  6:39       ` Ni, Ruiyu
2016-09-29 19:10         ` Carsey, Jaben
2016-09-30  4:13           ` Ni, Ruiyu
2016-09-30 15:30             ` Carsey, Jaben
2016-10-03 18:35               ` Rothman, Michael A
2016-10-03 20:38                 ` Carsey, Jaben
2016-10-11  8:08                   ` Ni, Ruiyu
2016-10-11  8:28                     ` Ni, Ruiyu
2016-10-11  8:46                       ` Yao, Jiewen
2016-10-11 14:44                       ` Yao, Jiewen
2016-10-12 21:04                         ` Carsey, Jaben
2016-10-13  1:07                           ` Yao, Jiewen
2016-09-21  6:44 ` [PATCH 18/45] MdeModulePkg/MdeModulePkg.dsc: Add capsule related component Jiewen Yao
2016-09-21  6:45 ` [PATCH 19/45] IntelFrameworkModulePkg/DxeCapsuleLib: Add ProcessCapsules() interface Jiewen Yao
2016-09-28  8:08   ` Fan, Jeff
2016-09-21  6:45 ` [PATCH 20/45] SecurityPkg/SecurityPkg.dec: Add PcdPkcs7CertBuffer PCD Jiewen Yao
2016-09-21  6:45 ` [PATCH 21/45] SecurityPkg/FmpAuthenticationPkcs7Lib: Add PKCS7 NULL class for FMP Jiewen Yao
2016-09-21  6:45 ` [PATCH 22/45] SecurityPkg/FmpAuthenticationRsa2048Sha256Lib: Add " Jiewen Yao
2016-09-21  6:45 ` [PATCH 23/45] SecurityPkg/SecurityPkg.dsc: Add FmpAuthentication*Lib Jiewen Yao
2016-09-28  4:56   ` Zhang, Chao B
2016-09-21  6:45 ` [PATCH 24/45] UefiCpuPkg/Include: Add Microcode FMP definition Jiewen Yao
2016-09-21  6:45 ` [PATCH 25/45] UefiCpuPkg/Include: Add MicrocodeFlashAccessLib header Jiewen Yao
2016-09-21  6:45 ` [PATCH 26/45] UefiCpuPkg/UefiCpuPkg.dec: Add Microcode capsule related definition Jiewen Yao
2016-09-21  6:45 ` [PATCH 27/45] UefiCpuPkg/MicrocodeUpdate: Add MicrocodeUpdate component Jiewen Yao
2016-09-27  8:41   ` Fan, Jeff
2016-09-21  6:45 ` [PATCH 28/45] UefiCpuPkg/MicrocodeFlashAccessLib: Add NULL MicrocodeFlashAccessLib Jiewen Yao
2016-09-21  6:45 ` [PATCH 29/45] UefiCpuPkg/MicrocodeCapsuleApp: Add MicrocodeCapsuleApp application Jiewen Yao
2016-09-21  6:45 ` [PATCH 30/45] UefiCpuPkg/UefiCpuPkg.dsc: Add MicrocodeCapsule related component Jiewen Yao
2016-09-21  6:45 ` [PATCH 31/45] QuarkPlatformPkg/PlatformFlashAccessLib: Add instance for capsule update Jiewen Yao
2016-09-21  6:45 ` [PATCH 32/45] QuarkPlatformPkg/SystemBiosDescriptor: Add Descriptor " Jiewen Yao
2016-09-21  6:45 ` [PATCH 33/45] QuarkPlatformPkg/SystemBiosUpdateConfig: Add capsule config file Jiewen Yao
2016-09-21  6:45 ` [PATCH 34/45] QuarkPlatformPkg/PlatformInit: Remove recovery PPI installation Jiewen Yao
2016-09-21  6:45 ` [PATCH 35/45] QuarkPlatformPkg/PlatformBootManager: Add capsule/recovery handling Jiewen Yao
2016-09-21  6:45 ` [PATCH 36/45] QuarkPlatformPkg/dsc/fdf: Add capsule/recovery support Jiewen Yao
2016-09-21  6:45 ` [PATCH 37/45] QuarkPlatformPkg/dsc/fdf: add capsule generation DSC/FDF Jiewen Yao
2016-09-29  1:01   ` Kinney, Michael D
2016-09-29  2:33     ` Yao, Jiewen
2016-09-21  6:45 ` [PATCH 38/45] Vlv2TbltDevicePkg/PlatformFlashAccessLib: Add instance for capsule update Jiewen Yao
2016-09-21  6:51   ` Wei, David
2016-09-21  6:45 ` [PATCH 39/45] Vlv2TbltDevicePkg/SystemBiosDescriptor: Add Descriptor " Jiewen Yao
2016-09-21  6:54   ` Wei, David
2016-09-21  6:45 ` [PATCH 40/45] Vlv2TbltDevicePkg/SystemBiosUpdateConfig: Add capsule config file Jiewen Yao
2016-09-21  6:57   ` Wei, David
2016-09-21  6:45 ` [PATCH 41/45] Vlv2TbltDevicePkg/FlashDeviceLib: Add DXE flash device lib Jiewen Yao
2016-09-21  7:10   ` Wei, David
2016-09-21  6:45 ` [PATCH 42/45] Vlv2TbltDevicePkg/PlatformBootManager: Add capsule/recovery handling Jiewen Yao
2016-09-22  2:40   ` Wei, David
2016-09-21  6:45 ` [PATCH 43/45] Vlv2TbltDevicePkg/dsc/fdf: Add capsule/recovery support Jiewen Yao
2016-09-22  1:36   ` Wei, David
2016-09-22  1:39   ` Wei, David
2016-09-21  6:45 ` [PATCH 44/45] Vlv2TbltDevicePkg/dsc/fdf: add capsule generation DSC/FDF Jiewen Yao
2016-09-21  6:45 ` [PATCH 45/45] Vlv2TbltDevicePkg/bat: add capsule generation in bat Jiewen Yao
2016-09-21  7:53   ` Wei, David
2016-09-21  7:54     ` Yao, Jiewen
2016-09-21 16:35 ` [PATCH 00/45] Add capsule update and recovery sample Kinney, Michael D
2016-09-22  1:59   ` Yao, Jiewen
2016-09-23  3:18 ` Gao, Liming
2016-09-24  6:42   ` Yao, Jiewen
2016-09-27  3:16 ` Gao, Liming
2016-09-28  8:05 ` Yao, Jiewen
2016-09-28 14:54   ` Kinney, Michael D

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