* [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 +
| 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."
--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 +
| 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."
+
--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