public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [PATCH V5 0/7] Add MicrocodeUpdate support.
@ 2016-10-27 13:46 Jiewen Yao
  2016-10-27 13:46 ` [PATCH V5 1/7] UefiCpuPkg/Include: Add Microcode FMP definition Jiewen Yao
                   ` (6 more replies)
  0 siblings, 7 replies; 8+ messages in thread
From: Jiewen Yao @ 2016-10-27 13:46 UTC (permalink / raw)
  To: edk2-devel
  Cc: Feng Tian, Star Zeng, Michael D Kinney, Liming Gao, Chao Zhang,
	Jeff Fan

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 10579 bytes --]

This is series 3 of the whole capsule solution. Version 5.
According to feedback, we split the big patch series to smaller one.

Series 3: Microcode Update (UefiCpuPkg)
	MicrocodeFlashAccessLib
	MicrocodeUpdate driver.

The code is also in https://github.com/jyao1/edk2
V5 is at Capsule_V5 branch.
V4, V3, V2, V1 are also pushed to coresponding branch.

==Below is V5 description==
1) MdeModulePkg/CapsuleApp: Remove [NR]. Add more description.
2) MdeModulePkg/DEC: Update StatusCode to OEM region.
3) MdeModulePkg/DxeCapsuleLib: Use NULL ProcessCapsules()
for runtime lib, because it is not needed for runtime.
4) MdeModulePkg/FmpAuthenticationLib: Add more description.
5) SignedCapsulePkg/DEC: Add data structure description
for PcdEdkiiSystemFirmwareImageDescriptor.
6) SignedCapsulePkg/DEC: Add Pkcs7 and Rsa2048 Key file PCD.
These 2 PCD are moved from platform pkg to SignedCapsulePkg.
7) QuarkPlatformPkg/FDF: Refine order of capsule section.
8) Fix typo and coding style issue.

Below items are defered to other patch series, because
the tool and library are not ready yet.

A) MdeModulePkg/DxeCapsuleLib: separate BMP parsing logic
to another library.
That is very good suggestion, and we agree it is a right direction.
I discussed with the owner of image decoder.
We prefer adding a generic library class to convert
the image data to GOP BLT buffer. It supports *any* image format,
not only BMP. The owner of image decoder will drive the new design.
I filed https://bugzilla.tianocore.org/show_bug.cgi?id=175 to track that.
I suggest we just keep the current solution as a temp solution and
migrate to the new one once it is ready later.

B) PlatformPkg/Bds: Move test key check logic to generic part.
This is very good suggestion and we are discussing with Tool
team to add such detection at build time and set a PCD to indicate that.
The generic code can use this PCD to know if there is a test key.
I filed https://bugzilla.tianocore.org/show_bug.cgi?id=185 to track that.
Adding such check in the generic code is very complicated, so current
temporary solution is to let platform BDS do such check.
The platform BDS will be cleaned up, once the tool is ready.

==Below is V4 description==
1) SecurityPkg - Refine AuthenticateFmpImage() API to let caller
input PublicKeyData and PublicKeyDataLength, instead of PCD.
The benefit is that then this API can be used for a platform
which stores PublicKeyData in anywhere other than PCD.
2) SecurityPkg - Use OFFSET_OF(WIN_CERTIFICATE_UEFI_GUID, CertData)
for better understanding the code.
3) MdeModulePkg - Update CapsuleApp to let it consume
ShellParameters protocol to get Argc and Argv.
4) UefiCpuPkg - Update MicrocodeCapsuleApp to let it consume
ShellParameters protocol to get Argc and Argv.
5) QuarkPlatformPkg - Merge QuarkCapsule.fdf to Quark.fdf.

==Below is V3 description==
1) We move all EDKII related capsule definition to SignedCapsulePkg.
MdeModulePkg only contains FmAuthenticationLib and CapsuleApp,
because they are generic and follow UEFI specification on FMP/ESRT
and Microsoft platform firmware update document.
Any capsule implementation can use them.

Here is full library classes:
MdeModulePkg:
	FmpAuthenticationLib.h: new lib - follow UEFI spec. (*)
		Verify FMP signature of FMP Capsule
	CapsuleLib.h: new API ¨C ProcessCapsules()
		It processes all the capsules. Remove duplicated code in platform BDS.
UefiCpuPkg:
	MicrocodeFlashAccessLib.h: Update Microcode region.
SignedCapsulePkg:
	EdkiiSystemCapsuleLib.h ¨C Library for EDKII system FMP.
	IniParsingLib.h ¨C Library for INI file parsing.
	PlatformFlashAccessLib.h ¨C Library for write flash.

2) We will submit 5 series.
Series 1: Generic Update (MdeModulePkg/SecurityPkg)
	DxeCapsuleLib
	FmAuthenticationLib (*)
	CapsuleApp (*)
Series 2: EDKII Capsule (SignedCapsulePkg)
	IniParsingLib
	EdkiiSystemCapsuleLib
	PlatformFlashAccessLib
	SystemFirmwareUpdate driver
	RecoveryModuleLoadPei driver
Series 3: Microcode Update (UefiCpuPkg)
	MicrocodeFlashAccessLib
	MicrocodeUpdate driver.
Series 4: Quark update
Series 5: Vlv2 update

3) DxeCapsuleLib: Move code that performs authentication and parsing of
the capsule format into the implementation of the FMP Protocol.
We move the dispatch FV code from CapsuleLib to SystemFirmwareReport.efi.
SystemFirmwareReport.efi supports SetImage() to verify and dispatch the
SystemFirmwareUpdate.efi, then pass thru SetImage() request to
SystemFirmwareUpdate.efi.

Now the DxeCapsuleLib is very clean and it does not have any EDKII
capsule format knowledge.

4) DxeCapsuleLib: Fix issue where a reset may be too soon.
Defer reset to 2nd pass.

5) DxeCapsuleLib: Boot mode check is removed. 
Capsule should be populated to system table even boot mode is not BIOS_UPDATE.

5) FmAuthenticationLib: Add zero ImageSize check.

6) FmAuthenticationLib: Remove Authentication Library Registration.
Each FMP Producer needs to carry its own auth algoritms(s).
Now we have FmpAuthenticationLibPkcs7 and FmpAuthenticationLibRsa2048Sha256.
No registration is needed.

7) FmAuthenticationLib: Move MonotonicCount handling after Payload
We confirmed with USWG to process MonotonicCount after PayLoad.

==Below is V2 description==
The V2 series patch incorporated the feedback for V1.

There are 3 major updates.
1) BDS is update to display a warning message if TEST key
is used to sign recovery image or capsule image.
So a production BIOS should always use its own production singing
key for the capsule image generation. A production BIOS should
never use test key.
2) IniParsingLib is enhanced to do more sanity check for invalid
input. The detail data format is added in IniParsingLib.h header
file. If there is any vialation, the OpenInitFile() API will
return failure.
3) The *Bios* keyword is renamed to *SystemFirmware* in any
header file or c file data structure definition.

The rest is minor update, such as add help info, clean
up debug message, coding style.

==Below is V1 description==
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 (7):
  UefiCpuPkg/Include: Add Microcode FMP definition.
  UefiCpuPkg/Include: Add MicrocodeFlashAccessLib header.
  UefiCpuPkg/UefiCpuPkg.dec: Add Microcode capsule related definition.
  UefiCpuPkg/MicrocodeFlashAccessLib: Add NULL MicrocodeFlashAccessLib.
  UefiCpuPkg/MicrocodeUpdate: Add MicrocodeUpdate component.
  UefiCpuPkg/MicrocodeCapsuleApp: Add MicrocodeCapsuleApp application.
  UefiCpuPkg/UefiCpuPkg.dsc: Add MicrocodeCapsule related component.

 UefiCpuPkg/Application/MicrocodeCapsuleApp/AppSupport.c                        | 443 +++++++++++
 UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.c               | 268 +++++++
 UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.inf             |  63 ++
 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                                      | 537 ++++++++++++++
 UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.c                                   | 779 ++++++++++++++++++++
 UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.h                                   | 403 ++++++++++
 UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.inf                                 |  68 ++
 UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdateDxe.uni                              |  21 +
 UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdateDxeExtra.uni                         |  20 +
 UefiCpuPkg/UefiCpuPkg.dec                                                      |   7 +
 UefiCpuPkg/UefiCpuPkg.dsc                                                      |   3 +
 19 files changed, 2987 insertions(+)
 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

-- 
2.7.4.windows.1



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

* [PATCH V5 1/7] UefiCpuPkg/Include: Add Microcode FMP definition.
  2016-10-27 13:46 [PATCH V5 0/7] Add MicrocodeUpdate support Jiewen Yao
@ 2016-10-27 13:46 ` Jiewen Yao
  2016-10-27 13:46 ` [PATCH V5 2/7] UefiCpuPkg/Include: Add MicrocodeFlashAccessLib header Jiewen Yao
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Jiewen Yao @ 2016-10-27 13:46 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>
Reviewed-by: Jeff Fan <jeff.fan@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] 8+ messages in thread

* [PATCH V5 2/7] UefiCpuPkg/Include: Add MicrocodeFlashAccessLib header.
  2016-10-27 13:46 [PATCH V5 0/7] Add MicrocodeUpdate support Jiewen Yao
  2016-10-27 13:46 ` [PATCH V5 1/7] UefiCpuPkg/Include: Add Microcode FMP definition Jiewen Yao
@ 2016-10-27 13:46 ` Jiewen Yao
  2016-10-27 13:46 ` [PATCH V5 3/7] UefiCpuPkg/UefiCpuPkg.dec: Add Microcode capsule related definition Jiewen Yao
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Jiewen Yao @ 2016-10-27 13:46 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>
Reviewed-by: Jeff Fan <jeff.fan@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..0dfc3ef
--- /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[in] FlashAddress      The address of flash device to be accessed.
+  @param[in] Buffer            The pointer to the data buffer.
+  @param[in] 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] 8+ messages in thread

* [PATCH V5 3/7] UefiCpuPkg/UefiCpuPkg.dec: Add Microcode capsule related definition.
  2016-10-27 13:46 [PATCH V5 0/7] Add MicrocodeUpdate support Jiewen Yao
  2016-10-27 13:46 ` [PATCH V5 1/7] UefiCpuPkg/Include: Add Microcode FMP definition Jiewen Yao
  2016-10-27 13:46 ` [PATCH V5 2/7] UefiCpuPkg/Include: Add MicrocodeFlashAccessLib header Jiewen Yao
@ 2016-10-27 13:46 ` Jiewen Yao
  2016-10-27 13:46 ` [PATCH V5 4/7] UefiCpuPkg/MicrocodeFlashAccessLib: Add NULL MicrocodeFlashAccessLib Jiewen Yao
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Jiewen Yao @ 2016-10-27 13:46 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>
Reviewed-by: Jeff Fan <jeff.fan@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] 8+ messages in thread

* [PATCH V5 4/7] UefiCpuPkg/MicrocodeFlashAccessLib: Add NULL MicrocodeFlashAccessLib.
  2016-10-27 13:46 [PATCH V5 0/7] Add MicrocodeUpdate support Jiewen Yao
                   ` (2 preceding siblings ...)
  2016-10-27 13:46 ` [PATCH V5 3/7] UefiCpuPkg/UefiCpuPkg.dec: Add Microcode capsule related definition Jiewen Yao
@ 2016-10-27 13:46 ` Jiewen Yao
  2016-10-27 13:46 ` [PATCH V5 5/7] UefiCpuPkg/MicrocodeUpdate: Add MicrocodeUpdate component Jiewen Yao
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Jiewen Yao @ 2016-10-27 13:46 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>
Reviewed-by: Jeff Fan <jeff.fan@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..7a5ec15
--- /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[in] FlashAddress      The address of flash device to be accessed.
+  @param[in] Buffer            The pointer to the data buffer.
+  @param[in] 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] 8+ messages in thread

* [PATCH V5 5/7] UefiCpuPkg/MicrocodeUpdate: Add MicrocodeUpdate component.
  2016-10-27 13:46 [PATCH V5 0/7] Add MicrocodeUpdate support Jiewen Yao
                   ` (3 preceding siblings ...)
  2016-10-27 13:46 ` [PATCH V5 4/7] UefiCpuPkg/MicrocodeFlashAccessLib: Add NULL MicrocodeFlashAccessLib Jiewen Yao
@ 2016-10-27 13:46 ` Jiewen Yao
  2016-10-27 13:46 ` [PATCH V5 6/7] UefiCpuPkg/MicrocodeCapsuleApp: Add MicrocodeCapsuleApp application Jiewen Yao
  2016-10-27 13:46 ` [PATCH V5 7/7] UefiCpuPkg/UefiCpuPkg.dsc: Add MicrocodeCapsule related component Jiewen Yao
  6 siblings, 0 replies; 8+ messages in thread
From: Jiewen Yao @ 2016-10-27 13:46 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>
Reviewed-by: Jeff Fan <jeff.fan@intel.com>
---
 UefiCpuPkg/MicrocodeUpdate/MicrocodeFmp.c              | 537 ++++++++++++++
 UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.c           | 779 ++++++++++++++++++++
 UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.h           | 403 ++++++++++
 UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.inf         |  68 ++
 UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdateDxe.uni      |  21 +
 UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdateDxeExtra.uni |  20 +
 6 files changed, 1828 insertions(+)

diff --git a/UefiCpuPkg/MicrocodeUpdate/MicrocodeFmp.c b/UefiCpuPkg/MicrocodeUpdate/MicrocodeFmp.c
new file mode 100644
index 0000000..50a6632
--- /dev/null
+++ b/UefiCpuPkg/MicrocodeUpdate/MicrocodeFmp.c
@@ -0,0 +1,537 @@
+/** @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"
+
+//
+// MicrocodeFmp driver private data
+//
+MICROCODE_FMP_PRIVATE_DATA *mMicrocodeFmpPrivate = NULL;
+
+EFI_FIRMWARE_MANAGEMENT_PROTOCOL mFirmwareManagementProtocol = {
+  FmpGetImageInfo,
+  FmpGetImage,
+  FmpSetImage,
+  FmpCheckImage,
+  FmpGetPackageInfo,
+  FmpSetPackageInfo
+};
+
+/**
+  Initialize Microcode Descriptor.
+
+  @param[in] 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[in] 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[in] 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[in]  ImageHandle       The firmware allocated handle for the EFI image.
+  @param[in]  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..4077e31
--- /dev/null
+++ b/UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.c
@@ -0,0 +1,779 @@
+/** @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[in] 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_INFO, "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[in]       ImageIndex The index of Microcode image.
+  @param[in, out]  Image      The Microcode image buffer.
+  @param[in, out]  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_INFO, "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.
+
+  Caution: This function may receive untrusted input.
+
+  @param[in]  Image              The Microcode image buffer.
+  @param[in]  ImageSize          The size of Microcode image buffer in bytes.
+  @param[in]  TryLoad            Try to load Microcode or not.
+  @param[out] LastAttemptStatus  The last attempt status, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+  @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 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_INFO, "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_INFO, "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[in]   Address            The flash address of Microcode.
+  @param[in]   Image              The Microcode image buffer.
+  @param[in]   ImageSize          The size of Microcode image buffer in bytes.
+  @param[out]  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.
+
+  Caution: This function may receive untrusted input.
+
+  @param[in]   ImageIndex         The index of Microcode image.
+  @param[in]   Image              The Microcode image buffer.
+  @param[in]   ImageSize          The size of Microcode image buffer 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.
+  @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 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..77e8441
--- /dev/null
+++ b/UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.h
@@ -0,0 +1,403 @@
+/** @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>
+
+#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 \
+  )
+
+/**
+  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[in]       ImageIndex The index of Microcode image.
+  @param[in, out]  Image      The Microcode image buffer.
+  @param[in, out]  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[in]   ImageIndex         The index of Microcode image.
+  @param[in]   Image              The Microcode image buffer.
+  @param[in]   ImageSize          The size of Microcode image buffer 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.
+  @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 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
+  );
+
+/**
+  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] 8+ messages in thread

* [PATCH V5 6/7] UefiCpuPkg/MicrocodeCapsuleApp: Add MicrocodeCapsuleApp application.
  2016-10-27 13:46 [PATCH V5 0/7] Add MicrocodeUpdate support Jiewen Yao
                   ` (4 preceding siblings ...)
  2016-10-27 13:46 ` [PATCH V5 5/7] UefiCpuPkg/MicrocodeUpdate: Add MicrocodeUpdate component Jiewen Yao
@ 2016-10-27 13:46 ` Jiewen Yao
  2016-10-27 13:46 ` [PATCH V5 7/7] UefiCpuPkg/UefiCpuPkg.dsc: Add MicrocodeCapsule related component Jiewen Yao
  6 siblings, 0 replies; 8+ messages in thread
From: Jiewen Yao @ 2016-10-27 13:46 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>
Reviewed-by: Jeff Fan <jeff.fan@intel.com>
---
 UefiCpuPkg/Application/MicrocodeCapsuleApp/AppSupport.c                 | 443 ++++++++++++++++++++
 UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.c        | 268 ++++++++++++
 UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.inf      |  63 +++
 UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.uni      |  22 +
 UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleAppExtra.uni |  19 +
 UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleDump.c       | 171 ++++++++
 6 files changed, 986 insertions(+)

diff --git a/UefiCpuPkg/Application/MicrocodeCapsuleApp/AppSupport.c b/UefiCpuPkg/Application/MicrocodeCapsuleApp/AppSupport.c
new file mode 100644
index 0000000..0ab016c
--- /dev/null
+++ b/UefiCpuPkg/Application/MicrocodeCapsuleApp/AppSupport.c
@@ -0,0 +1,443 @@
+/** @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/ShellParameters.h>
+#include <Guid/FileInfo.h>
+#include <Guid/Gpt.h>
+
+UINTN  Argc = 0;
+CHAR16 **Argv;
+
+/**
+
+  This function parse application ARG.
+
+  @return Status
+**/
+EFI_STATUS
+GetArg (
+  VOID
+  )
+{
+  EFI_STATUS                    Status;
+  EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters;
+
+  Status = gBS->HandleProtocol (
+                  gImageHandle,
+                  &gEfiShellParametersProtocolGuid,
+                  (VOID**)&ShellParameters
+                  );
+  if (EFI_ERROR(Status)) {
+    return Status;
+  }
+
+  Argc = ShellParameters->Argc;
+  Argv = ShellParameters->Argv;
+  return EFI_SUCCESS;
+}
+
+/**
+  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[in]  Vol             File System Volume
+  @param[in]  FileName        The file to be read.
+  @param[out] BufferSize      The file buffer size
+  @param[out] 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[in]  ThisVol         File System Volume
+  @param[in]  FileName        The file to be read.
+  @param[out] BufferSize      The file buffer size
+  @param[out] Buffer          The file buffer
+  @param[in]  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[in]  FileName        The file to be read.
+  @param[out] BufferSize      The file buffer size
+  @param[out] 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[in] FileName        The file to be written.
+  @param[in] BufferSize      The file buffer size
+  @param[in] 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..aaa4399
--- /dev/null
+++ b/UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.c
@@ -0,0 +1,268 @@
+/** @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_CAPSULE_NUM 10
+
+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[in] FileName        The file to be read.
+  @param[in] BufferSize      The file buffer size
+  @param[in] 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[in] FileName        The file to be written.
+  @param[in] BufferSize      The file buffer size
+  @param[in] 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
+  );
+
+/**
+  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");
+    return EFI_UNSUPPORTED;
+  }
+  if (MicrocodeNum > MAX_CAPSULE_NUM) {
+    Print(L"CapsuleApp: Too many Microcode images.\n");
+    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)) {
+    Print(L"Please use UEFI SHELL to run this application!\n", Status);
+    return Status;
+  }
+  if (Argc < 2) {
+    PrintUsage();
+    return EFI_INVALID_PARAMETER;
+  }
+  if (StrCmp(Argv[1], L"-D") == 0) {
+    Status = DumpCapsule();
+    return Status;
+  }
+  if (StrCmp(Argv[1], L"-U") == 0) {
+    Status = CreateMicrocodeFmp();
+    return Status;
+  }
+
+  Status = EFI_UNSUPPORTED;
+
+  return Status;
+}
diff --git a/UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.inf b/UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.inf
new file mode 100644
index 0000000..d6a5c85
--- /dev/null
+++ b/UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.inf
@@ -0,0 +1,63 @@
+##  @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
+  gEfiShellParametersProtocolGuid
+
+[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..48a1579
--- /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[in]  FileName        The file to be read.
+  @param[out] BufferSize      The file buffer size
+  @param[out] 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[in] Image      The Microcode FMP capsule.
+  @param[in] 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[in]  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] 8+ messages in thread

* [PATCH V5 7/7] UefiCpuPkg/UefiCpuPkg.dsc: Add MicrocodeCapsule related component.
  2016-10-27 13:46 [PATCH V5 0/7] Add MicrocodeUpdate support Jiewen Yao
                   ` (5 preceding siblings ...)
  2016-10-27 13:46 ` [PATCH V5 6/7] UefiCpuPkg/MicrocodeCapsuleApp: Add MicrocodeCapsuleApp application Jiewen Yao
@ 2016-10-27 13:46 ` Jiewen Yao
  6 siblings, 0 replies; 8+ messages in thread
From: Jiewen Yao @ 2016-10-27 13:46 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>
Reviewed-by: Jeff Fan <jeff.fan@intel.com>
---
 UefiCpuPkg/UefiCpuPkg.dsc | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/UefiCpuPkg/UefiCpuPkg.dsc b/UefiCpuPkg/UefiCpuPkg.dsc
index bfe0fbd..fab87ad 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
@@ -131,6 +132,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] 8+ messages in thread

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

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-10-27 13:46 [PATCH V5 0/7] Add MicrocodeUpdate support Jiewen Yao
2016-10-27 13:46 ` [PATCH V5 1/7] UefiCpuPkg/Include: Add Microcode FMP definition Jiewen Yao
2016-10-27 13:46 ` [PATCH V5 2/7] UefiCpuPkg/Include: Add MicrocodeFlashAccessLib header Jiewen Yao
2016-10-27 13:46 ` [PATCH V5 3/7] UefiCpuPkg/UefiCpuPkg.dec: Add Microcode capsule related definition Jiewen Yao
2016-10-27 13:46 ` [PATCH V5 4/7] UefiCpuPkg/MicrocodeFlashAccessLib: Add NULL MicrocodeFlashAccessLib Jiewen Yao
2016-10-27 13:46 ` [PATCH V5 5/7] UefiCpuPkg/MicrocodeUpdate: Add MicrocodeUpdate component Jiewen Yao
2016-10-27 13:46 ` [PATCH V5 6/7] UefiCpuPkg/MicrocodeCapsuleApp: Add MicrocodeCapsuleApp application Jiewen Yao
2016-10-27 13:46 ` [PATCH V5 7/7] UefiCpuPkg/UefiCpuPkg.dsc: Add MicrocodeCapsule related component Jiewen Yao

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