Date   

[PATCH 39/45] Vlv2TbltDevicePkg/SystemBiosDescriptor: Add Descriptor for capsule update.

Yao, Jiewen
 

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

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

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


[PATCH 38/45] Vlv2TbltDevicePkg/PlatformFlashAccessLib: Add instance for capsule update.

Yao, Jiewen
 

Add PlatformFlashAccessLib for capsule update.

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

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


[PATCH 37/45] QuarkPlatformPkg/dsc/fdf: add capsule generation DSC/FDF.

Yao, Jiewen
 

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

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

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


[PATCH 36/45] QuarkPlatformPkg/dsc/fdf: Add capsule/recovery support.

Yao, Jiewen
 

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

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

diff --git a/QuarkPlatformPkg/Quark.dsc b/QuarkPlatformPkg/Quark.dsc
index 51a7b63..67d0a1e 100644
--- a/QuarkPlatformPkg/Quark.dsc
+++ b/QuarkPlatformPkg/Quark.dsc
@@ -39,6 +39,8 @@
DEFINE SOURCE_DEBUG_ENABLE = FALSE
DEFINE PERFORMANCE_ENABLE = FALSE
DEFINE LOGGING = FALSE
+ DEFINE CAPSULE_ENABLE = FALSE
+ DEFINE RECOVERY_ENABLE = FALSE

#
# Galileo board. Options are [GEN1, GEN2]
@@ -160,11 +162,9 @@
PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf
!endif

-!if $(SECURE_BOOT_ENABLE) || $(MEASURED_BOOT_ENABLE)
OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLib.inf
IntrinsicLib|CryptoPkg/Library/IntrinsicLib/IntrinsicLib.inf
BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
-!endif

!if $(SECURE_BOOT_ENABLE)
PlatformSecureLib|QuarkPlatformPkg/Library/PlatformSecureLib/PlatformSecureLib.inf
@@ -226,6 +226,17 @@
PlatformPcieHelperLib|QuarkPlatformPkg/Library/PlatformPcieHelperLib/PlatformPcieHelperLib.inf
PlatformHelperLib|QuarkPlatformPkg/Library/PlatformHelperLib/DxePlatformHelperLib.inf

+!if $(CAPSULE_ENABLE)
+ CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.inf
+!else
+ CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf
+!endif
+
+ EdkiiSystemCapsuleLib|MdeModulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.inf
+ FmpAuthenticationLib|MdeModulePkg/Library/FmpAuthenitcationLib/FmpAuthenitcationLib.inf
+ IniParsingLib|MdeModulePkg/Library/IniParsingLib/IniParsingLib.inf
+ PlatformFlashAccessLib|QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLibDxe.inf
+
[LibraryClasses.common.SEC]
#
# SEC specific phase
@@ -251,9 +262,7 @@
PlatformHelperLib|QuarkPlatformPkg/Library/PlatformHelperLib/PeiPlatformHelperLib.inf
CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.inf
MpInitLib|UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf
-!if $(SECURE_BOOT_ENABLE) || $(MEASURED_BOOT_ENABLE)
BaseCryptLib|CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
-!endif
!if $(PERFORMANCE_ENABLE)
PerformanceLib|MdeModulePkg/Library/PeiPerformanceLib/PeiPerformanceLib.inf
!endif
@@ -274,9 +283,7 @@
PciLib|MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf
CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/SmmCpuExceptionHandlerLib.inf
SmmMemLib|MdePkg/Library/SmmMemLib/SmmMemLib.inf
-!if $(SECURE_BOOT_ENABLE) || $(MEASURED_BOOT_ENABLE)
BaseCryptLib|CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
-!endif
!if $(PERFORMANCE_ENABLE)
PerformanceLib|MdeModulePkg/Library/SmmPerformanceLib/SmmPerformanceLib.inf
!endif
@@ -302,6 +309,10 @@
BaseCryptLib|CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf
!endif

+!if $(CAPSULE_ENABLE)
+ CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf
+!endif
+
[LibraryClasses.IA32.UEFI_DRIVER,LibraryClasses.IA32.UEFI_APPLICATION]
PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf

@@ -450,6 +461,11 @@
gQuarkPlatformTokenSpaceGuid.PcdUserIsPhysicallyPresent|FALSE
gQuarkPlatformTokenSpaceGuid.PcdSpiFlashDeviceSize|0

+!if $(CAPSULE_ENABLE) || $(RECOVERY_ENABLE)
+ gEfiMdeModulePkgTokenSpaceGuid.PcdEdkiiSystemFirmwareImageDescriptor|{0x0}|VOID*|0x100
+ gEfiMdeModulePkgTokenSpaceGuid.PcdEdkiiSystemFmpCapsuleImageTypeIdGuid|{0xc0, 0x20, 0xaf, 0x62, 0x16, 0x70, 0x4a, 0x42, 0x9b, 0xf8, 0x9c, 0xcc, 0x86, 0x58, 0x40, 0x90}
+!endif
+
!if $(MEASURED_BOOT_ENABLE)
#
# TPM1.2 { 0x8b01e5b6, 0x4f19, 0x46e8, { 0xab, 0x93, 0x1c, 0x53, 0x67, 0x1b, 0x90, 0xcc } }
@@ -541,6 +557,11 @@
!endif
}

+!if $(CAPSULE_ENABLE) || $(RECOVERY_ENABLE)
+ # FMP image decriptor
+ QuarkPlatformPkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptor.inf
+!endif
+
#
# PEI Core
#
@@ -595,6 +616,7 @@
#
# Recovery
#
+!if $(RECOVERY_ENABLE)
QuarkSocPkg/QuarkSouthCluster/Usb/Common/Pei/UsbPei.inf
MdeModulePkg/Bus/Pci/EhciPei/EhciPei.inf
QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/OhciPei.inf
@@ -602,6 +624,11 @@
MdeModulePkg/Bus/Usb/UsbBusPei/UsbBusPei.inf
FatPkg/FatPei/FatPei.inf
MdeModulePkg/Universal/Disk/CdExpressPei/CdExpressPei.inf
+ MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPei.inf {
+ <LibraryClasses>
+ NULL|SecurityPkg/Library/FmpAuthenticationRsa2048Sha256Lib/FmpAuthenticationRsa2048Sha256Lib.inf
+ }
+!endif

[Components.IA32]
#
@@ -646,11 +673,7 @@
NULL|MdeModulePkg/Library/VarCheckPcdLib/VarCheckPcdLib.inf
}

- MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf {
- <LibraryClasses>
- GenericBdsLib|IntelFrameworkModulePkg/Library/GenericBdsLib/GenericBdsLib.inf
- CapsuleLib|IntelFrameworkModulePkg/Library/DxeCapsuleLib/DxeCapsuleLib.inf
- }
+ MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf
MdeModulePkg/Universal/ResetSystemRuntimeDxe/ResetSystemRuntimeDxe.inf
PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcatRealTimeClockRuntimeDxe.inf
@@ -676,6 +699,7 @@
<LibraryClasses>
UefiBootManagerLib|MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf
PlatformBootManagerLib|QuarkPlatformPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf
+ NULL|SecurityPkg/Library/FmpAuthenticationPkcs7Lib/FmpAuthenticationPkcs7Lib.inf
}
MdeModulePkg/Application/UiApp/UiApp.inf {
<LibraryClasses>
@@ -885,5 +909,20 @@
gEfiMdePkgTokenSpaceGuid.PcdUefiLibMaxPrintBufferSize|8000
}

+!if $(CAPSULE_ENABLE)
+ MdeModulePkg/Universal/EsrtDxe/EsrtDxe.inf
+
+ MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxe.inf
+ MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxe.inf {
+ <LibraryClasses>
+ NULL|SecurityPkg/Library/FmpAuthenticationPkcs7Lib/FmpAuthenticationPkcs7Lib.inf
+ }
+
+ MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf {
+ <LibraryClasses>
+ PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
+ }
+!endif
+
[BuildOptions.common.EDKII.DXE_RUNTIME_DRIVER]
MSFT:*_*_*_DLINK_FLAGS = /ALIGN:4096
diff --git a/QuarkPlatformPkg/Quark.fdf b/QuarkPlatformPkg/Quark.fdf
index 9f51eb3..caa5736 100644
--- a/QuarkPlatformPkg/Quark.fdf
+++ b/QuarkPlatformPkg/Quark.fdf
@@ -317,6 +317,11 @@ APRIORI PEI {
##
INF UefiCpuPkg/SecCore/SecCore.inf

+!if $(CAPSULE_ENABLE) || $(RECOVERY_ENABLE)
+ # FMP image decriptor
+INF RuleOverride = FMP_IMAGE_DESC QuarkPlatformPkg/Feature/Capsule/SystemBiosDescriptor/SystemBiosDescriptor.inf
+!endif
+
INF MdeModulePkg/Core/Pei/PeiMain.inf

##
@@ -347,12 +352,16 @@ INF SecurityPkg/Tcg/TrEEConfig/TrEEConfigPei.inf
INF SecurityPkg/Tcg/TcgPei/TcgPei.inf
!endif

+!if $(RECOVERY_ENABLE)
FILE FV_IMAGE = 1E9D7604-EF45-46a0-BD8A-71AC78C17AC1 {
SECTION PEI_DEPEX_EXP = {gEfiPeiMemoryDiscoveredPpiGuid AND gEfiPeiBootInRecoveryModePpiGuid}
SECTION GUIDED A31280AD-481E-41B6-95E8-127F4C984779 { # TIANO COMPRESS GUID
SECTION FV_IMAGE = FVRECOVERY_COMPONENTS
}
}
+!endif
+
+!if $(RECOVERY_ENABLE)

################################################################################
#
@@ -390,6 +399,9 @@ INF MdeModulePkg/Bus/Usb/UsbBusPei/UsbBusPei.inf
INF MdeModulePkg/Bus/Usb/UsbBotPei/UsbBotPei.inf
INF FatPkg/FatPei/FatPei.inf
INF MdeModulePkg/Universal/Disk/CdExpressPei/CdExpressPei.inf
+INF MdeModulePkg/Universal/RecoveryModuleLoadPei/RecoveryModuleLoadPei.inf
+
+!endif

################################################################################
#
@@ -579,6 +591,11 @@ INF SecurityPkg/Tcg/TcgDxe/TcgDxe.inf
INF RuleOverride = DRIVER_ACPITABLE SecurityPkg/Tcg/TcgSmm/TcgSmm.inf
!endif

+!if $(CAPSULE_ENABLE)
+INF MdeModulePkg/Universal/EsrtDxe/EsrtDxe.inf
+INF MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosReportDxe.inf
+!endif
+
################################################################################
#
# FV Section
@@ -650,6 +667,32 @@ INF RuleOverride = TIANOCOMPRESSED ShellPkg/Application/Shell/Shell.inf
INF RuleOverride = TIANOCOMPRESSED PerformancePkg/Dp_App/Dp.inf
!endif

+!if $(CAPSULE_ENABLE) || $(RECOVERY_ENABLE)
+
+[FV.CapsuleDispatchFv]
+FvAlignment = 16
+ERASE_POLARITY = 1
+MEMORY_MAPPED = TRUE
+STICKY_WRITE = TRUE
+LOCK_CAP = TRUE
+LOCK_STATUS = TRUE
+WRITE_DISABLED_CAP = TRUE
+WRITE_ENABLED_CAP = TRUE
+WRITE_STATUS = TRUE
+WRITE_LOCK_CAP = TRUE
+WRITE_LOCK_STATUS = TRUE
+READ_DISABLED_CAP = TRUE
+READ_ENABLED_CAP = TRUE
+READ_STATUS = TRUE
+READ_LOCK_CAP = TRUE
+READ_LOCK_STATUS = TRUE
+
+!if $(CAPSULE_ENABLE)
+INF MdeModulePkg/Universal/SystemBiosUpdate/SystemBiosUpdateDxe.inf
+!endif
+
+!endif
+
################################################################################
#
# Rules are use with the [FV] section's module INF type to define
@@ -771,3 +814,13 @@ INF RuleOverride = TIANOCOMPRESSED PerformancePkg/Dp_App/Dp.inf
RAW ACPI |.acpi
RAW ASL |.aml
}
+
+[Rule.Common.PEIM.FMP_IMAGE_DESC]
+ FILE PEIM = $(NAMED_GUID) {
+ RAW BIN |.acpi
+ PEI_DEPEX PEI_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex
+ PE32 PE32 Align=4K $(INF_OUTPUT)/$(MODULE_NAME).efi
+ UI STRING="$(MODULE_NAME)" Optional
+ VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+ }
+
diff --git a/QuarkPlatformPkg/QuarkMin.dsc b/QuarkPlatformPkg/QuarkMin.dsc
index 99ae067..05ed6e6 100644
--- a/QuarkPlatformPkg/QuarkMin.dsc
+++ b/QuarkPlatformPkg/QuarkMin.dsc
@@ -161,6 +161,8 @@
AuthVariableLib|MdeModulePkg/Library/AuthVariableLibNull/AuthVariableLibNull.inf
!endif

+ CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf
+
#
# CPU
#
@@ -548,10 +550,7 @@
MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf
MdeModulePkg/Core/RuntimeDxe/RuntimeDxe.inf
MdeModulePkg/Universal/Variable/EmuRuntimeDxe/EmuVariableRuntimeDxe.inf
- MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf {
- <LibraryClasses>
- CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf
- }
+ MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf
MdeModulePkg/Universal/ResetSystemRuntimeDxe/ResetSystemRuntimeDxe.inf
PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcatRealTimeClockRuntimeDxe.inf
--
2.7.4.windows.1


[PATCH 35/45] QuarkPlatformPkg/PlatformBootManager: Add capsule/recovery handling.

Yao, Jiewen
 

Add capsule and recovery boot path handling in platform BDS.

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

diff --git a/QuarkPlatformPkg/Library/PlatformBootManagerLib/PlatformBootManager.c b/QuarkPlatformPkg/Library/PlatformBootManagerLib/PlatformBootManager.c
index 19ff3d0..6a295ed 100644
--- a/QuarkPlatformPkg/Library/PlatformBootManagerLib/PlatformBootManager.c
+++ b/QuarkPlatformPkg/Library/PlatformBootManagerLib/PlatformBootManager.c
@@ -2,7 +2,7 @@
This file include all platform action which can be customized
by IBV/OEM.

-Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
@@ -205,6 +205,8 @@ PlatformBootManagerBeforeConsole (
EFI_INPUT_KEY Enter;
EFI_INPUT_KEY F2;
EFI_BOOT_MANAGER_LOAD_OPTION BootOption;
+ ESRT_MANAGEMENT_PROTOCOL *EsrtManagement;
+ EFI_BOOT_MODE BootMode;
EFI_ACPI_S3_SAVE_PROTOCOL *AcpiS3Save;
EFI_HANDLE Handle;
EFI_EVENT EndOfDxeEvent;
@@ -246,6 +248,40 @@ PlatformBootManagerBeforeConsole (
//
PlatformRegisterFvBootOption (&mUefiShellFileGuid, L"UEFI Shell", LOAD_OPTION_ACTIVE);

+ Status = gBS->LocateProtocol(&gEsrtManagementProtocolGuid, NULL, (VOID **)&EsrtManagement);
+ if (EFI_ERROR(Status)) {
+ EsrtManagement = NULL;
+ }
+
+ BootMode = GetBootModeHob();
+ switch (BootMode) {
+ case BOOT_ON_FLASH_UPDATE:
+ DEBUG((EFI_D_INFO, "ProcessCapsules Before EndOfDxe ......\n"));
+ Status = ProcessCapsules ();
+ DEBUG((EFI_D_INFO, "ProcessCapsules %r\n", Status));
+ break;
+ case BOOT_IN_RECOVERY_MODE:
+ break;
+ case BOOT_ASSUMING_NO_CONFIGURATION_CHANGES:
+ case BOOT_WITH_MINIMAL_CONFIGURATION:
+ case BOOT_ON_S4_RESUME:
+ if (EsrtManagement != NULL) {
+ //
+ // Lock ESRT cache repository before EndofDxe if ESRT sync is not needed
+ //
+ EsrtManagement->LockEsrtRepository();
+ }
+ break;
+ default:
+ //
+ // Require to sync ESRT from FMP in a new boot
+ //
+ if (EsrtManagement != NULL) {
+ EsrtManagement->SyncEsrtFmp();
+ }
+ break;
+ }
+
//
// Prepare for S3
//
@@ -303,7 +339,62 @@ PlatformBootManagerAfterConsole (
VOID
)
{
- EFI_STATUS Status;
+ EFI_STATUS Status;
+ EFI_BOOT_MODE BootMode;
+ ESRT_MANAGEMENT_PROTOCOL *EsrtManagement;
+
+ Status = gBS->LocateProtocol(&gEsrtManagementProtocolGuid, NULL, (VOID **)&EsrtManagement);
+ if (EFI_ERROR(Status)) {
+ EsrtManagement = NULL;
+ }
+
+ BootMode = GetBootModeHob();
+ switch (BootMode) {
+ case BOOT_ON_FLASH_UPDATE:
+ DEBUG((EFI_D_INFO, "Capsule Mode detected\n"));
+ if (FeaturePcdGet(PcdSupportUpdateCapsuleReset)) {
+ EfiBootManagerConnectAll ();
+ EfiBootManagerRefreshAllBootOption ();
+
+ //
+ // Always sync ESRT Cache from FMP Instances after connect all and before capsule process
+ //
+ if (EsrtManagement != NULL) {
+ EsrtManagement->SyncEsrtFmp();
+ }
+
+ DEBUG((EFI_D_INFO, "ProcessCapsules After ConnectAll ......\n"));
+ Status = ProcessCapsules();
+ DEBUG((EFI_D_INFO, "ProcessCapsules %r\n", Status));
+ }
+ break;
+
+ case BOOT_IN_RECOVERY_MODE:
+ DEBUG((EFI_D_INFO, "Recovery Mode detected\n"));
+ // Passthrough
+
+ case BOOT_ASSUMING_NO_CONFIGURATION_CHANGES:
+ case BOOT_WITH_MINIMAL_CONFIGURATION:
+ case BOOT_WITH_FULL_CONFIGURATION:
+ case BOOT_WITH_FULL_CONFIGURATION_PLUS_DIAGNOSTICS:
+ case BOOT_WITH_DEFAULT_SETTINGS:
+ default:
+ EfiBootManagerConnectAll ();
+ EfiBootManagerRefreshAllBootOption ();
+
+ //
+ // Sync ESRT Cache from FMP Instance on demand after Connect All
+ //
+ if ((BootMode != BOOT_ASSUMING_NO_CONFIGURATION_CHANGES) &&
+ (BootMode != BOOT_WITH_MINIMAL_CONFIGURATION) &&
+ (BootMode != BOOT_ON_S4_RESUME)) {
+ if (EsrtManagement != NULL) {
+ EsrtManagement->SyncEsrtFmp();
+ }
+ }
+
+ break;
+ }

Print (
L"\n"
diff --git a/QuarkPlatformPkg/Library/PlatformBootManagerLib/PlatformBootManager.h b/QuarkPlatformPkg/Library/PlatformBootManagerLib/PlatformBootManager.h
index 7413883..683249b 100644
--- a/QuarkPlatformPkg/Library/PlatformBootManagerLib/PlatformBootManager.h
+++ b/QuarkPlatformPkg/Library/PlatformBootManagerLib/PlatformBootManager.h
@@ -1,7 +1,7 @@
/** @file
Head file for BDS Platform specific code

-Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
@@ -21,6 +21,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include <Protocol/FirmwareVolume2.h>
#include <Protocol/AcpiS3Save.h>
#include <Protocol/DxeSmmReadyToLock.h>
+#include <Protocol/EsrtManagement.h>
#include <Guid/DebugAgentGuid.h>
#include <Guid/EventGroup.h>
#include <Guid/PcAnsi.h>
@@ -32,9 +33,12 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include <Library/DevicePathLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
#include <Library/UefiLib.h>
#include <Library/UefiBootManagerLib.h>
-
+#include <Library/PrintLib.h>
+#include <Library/HobLib.h>
+#include <Library/CapsuleLib.h>

typedef struct {
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
diff --git a/QuarkPlatformPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf b/QuarkPlatformPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf
index d59f14a..5526562 100644
--- a/QuarkPlatformPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf
+++ b/QuarkPlatformPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf
@@ -1,7 +1,7 @@
## @file
# Include all platform action which can be customized by IBV/OEM.
#
-# Copyright (c) 2012 - 2015, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2012 - 2016, Intel Corporation. All rights reserved.<BR>
# This program and the accompanying materials
# are licensed and made available under the terms and conditions of the BSD License
# which accompanies this distribution. The full text of the license may be found at
@@ -49,11 +49,15 @@
UefiBootServicesTableLib
UefiLib
UefiBootManagerLib
+ PrintLib
+ HobLib
+ CapsuleLib

[Protocols]
gEfiFirmwareVolume2ProtocolGuid
gEfiAcpiS3SaveProtocolGuid
gEfiDxeSmmReadyToLockProtocolGuid
+ gEsrtManagementProtocolGuid

[Guids]
gEfiPcAnsiGuid
@@ -70,3 +74,5 @@
gEfiMdePkgTokenSpaceGuid.PcdUartDefaultStopBits
gEfiMdePkgTokenSpaceGuid.PcdDefaultTerminalType
gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdBootState
+ gEfiMdeModulePkgTokenSpaceGuid.PcdSupportUpdateCapsuleReset
+
--
2.7.4.windows.1


[PATCH 34/45] QuarkPlatformPkg/PlatformInit: Remove recovery PPI installation.

Yao, Jiewen
 

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

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

diff --git a/QuarkPlatformPkg/Platform/Pei/PlatformInit/MemoryCallback.c b/QuarkPlatformPkg/Platform/Pei/PlatformInit/MemoryCallback.c
index d5fb941..f9b769d 100644
--- a/QuarkPlatformPkg/Platform/Pei/PlatformInit/MemoryCallback.c
+++ b/QuarkPlatformPkg/Platform/Pei/PlatformInit/MemoryCallback.c
@@ -222,8 +222,7 @@ MemoryDiscoveredPpiNotifyCallback (
QNCPortWrite (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC, RegData32);

if (BootMode == BOOT_IN_RECOVERY_MODE) {
- Status = PeimInitializeRecovery (PeiServices);
- ASSERT_EFI_ERROR (Status);
+ // Do nothing here. A generic RecoveryModule will handle it.
} else if (BootMode == BOOT_ON_S3_RESUME) {
return EFI_SUCCESS;
} else {
--
2.7.4.windows.1


[PATCH 33/45] QuarkPlatformPkg/SystemBiosUpdateConfig: Add capsule config file.

Yao, Jiewen
 

Add SystemBiosUpdateConfig as capsule configuration file.

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

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


[PATCH 32/45] QuarkPlatformPkg/SystemBiosDescriptor: Add Descriptor for capsule update.

Yao, Jiewen
 

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

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

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


[PATCH 31/45] QuarkPlatformPkg/PlatformFlashAccessLib: Add instance for capsule update.

Yao, Jiewen
 

Add PlatformFlashAccessLib for capsule update.

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

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


[PATCH 30/45] UefiCpuPkg/UefiCpuPkg.dsc: Add MicrocodeCapsule related component.

Yao, Jiewen
 

Add Microcode capsule related component to check build.

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

diff --git a/UefiCpuPkg/UefiCpuPkg.dsc b/UefiCpuPkg/UefiCpuPkg.dsc
index d4a6673..78316de 100644
--- a/UefiCpuPkg/UefiCpuPkg.dsc
+++ b/UefiCpuPkg/UefiCpuPkg.dsc
@@ -61,6 +61,7 @@
SmmCpuFeaturesLib|UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLib.inf
PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf
+ MicrocodeFlashAccessLib|UefiCpuPkg/Library/MicrocodeFlashAccessLibNull/MicrocodeFlashAccessLibNull.inf

[LibraryClasses.common.SEC]
PlatformSecLib|UefiCpuPkg/Library/PlatformSecLibNull/PlatformSecLibNull.inf
@@ -128,6 +129,8 @@
UefiCpuPkg/SecCore/SecCore.inf
UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf
UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume2Pei.inf
+ UefiCpuPkg/MicrocodeUpdate/MicrocodeUpdate.inf
+ UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.inf

[BuildOptions]
*_*_*_CC_FLAGS = -D DISABLE_NEW_DEPRECATED_INTERFACES
--
2.7.4.windows.1


[PATCH 29/45] UefiCpuPkg/MicrocodeCapsuleApp: Add MicrocodeCapsuleApp application.

Yao, Jiewen
 

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

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

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


[PATCH 28/45] UefiCpuPkg/MicrocodeFlashAccessLib: Add NULL MicrocodeFlashAccessLib.

Yao, Jiewen
 

Add NULL instance to pass build.

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

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


[PATCH 27/45] UefiCpuPkg/MicrocodeUpdate: Add MicrocodeUpdate component.

Yao, Jiewen
 

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

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


[PATCH 26/45] UefiCpuPkg/UefiCpuPkg.dec: Add Microcode capsule related definition.

Yao, Jiewen
 

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

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


[PATCH 25/45] UefiCpuPkg/Include: Add MicrocodeFlashAccessLib header.

Yao, Jiewen
 

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

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


[PATCH 24/45] UefiCpuPkg/Include: Add Microcode FMP definition.

Yao, Jiewen
 

It defined ImageTypeId for Microcode.

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


[PATCH 23/45] SecurityPkg/SecurityPkg.dsc: Add FmpAuthentication*Lib.

Yao, Jiewen
 

Add FmpAuthentication*Lib to check build.

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

diff --git a/SecurityPkg/SecurityPkg.dsc b/SecurityPkg/SecurityPkg.dsc
index 3b36d0f..09d083e 100644
--- a/SecurityPkg/SecurityPkg.dsc
+++ b/SecurityPkg/SecurityPkg.dsc
@@ -211,6 +211,9 @@
SecurityPkg/Library/DxeRsa2048Sha256GuidedSectionExtractLib/DxeRsa2048Sha256GuidedSectionExtractLib.inf
SecurityPkg/Library/PeiRsa2048Sha256GuidedSectionExtractLib/PeiRsa2048Sha256GuidedSectionExtractLib.inf

+ SecurityPkg/Library/FmpAuthenticationPkcs7Lib/FmpAuthenticationPkcs7Lib.inf
+ SecurityPkg/Library/FmpAuthenticationRsa2048Sha256Lib/FmpAuthenticationRsa2048Sha256Lib.inf
+
SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf

[Components.IA32, Components.X64, Components.IPF]
--
2.7.4.windows.1


[PATCH 22/45] SecurityPkg/FmpAuthenticationRsa2048Sha256Lib: Add NULL class for FMP.

Yao, Jiewen
 

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

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

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


[PATCH 21/45] SecurityPkg/FmpAuthenticationPkcs7Lib: Add PKCS7 NULL class for FMP.

Yao, Jiewen
 

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

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

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


[PATCH 20/45] SecurityPkg/SecurityPkg.dec: Add PcdPkcs7CertBuffer PCD.

Yao, Jiewen
 

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

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

diff --git a/SecurityPkg/SecurityPkg.dec b/SecurityPkg/SecurityPkg.dec
index f4f4d19..156fc48 100644
--- a/SecurityPkg/SecurityPkg.dec
+++ b/SecurityPkg/SecurityPkg.dec
@@ -405,6 +405,12 @@
#
gEfiSecurityPkgTokenSpaceGuid.PcdRsa2048Sha256PublicKeyBuffer|{0x91, 0x29, 0xc4, 0xbd, 0xea, 0x6d, 0xda, 0xb3, 0xaa, 0x6f, 0x50, 0x16, 0xfc, 0xdb, 0x4b, 0x7e, 0x3c, 0xd6, 0xdc, 0xa4, 0x7a, 0x0e, 0xdd, 0xe6, 0x15, 0x8c, 0x73, 0x96, 0xa2, 0xd4, 0xa6, 0x4d}|VOID*|0x00010013

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