summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGuo, Mang <mang.guo@intel.com>2016-03-29 06:02:45 +0000
committerzwei4 <david.wei@intel.com>2016-04-12 15:43:16 +0800
commit3e11f7eb7174302bb350664e402552ea1bea399d (patch)
treea70f6a6dab0d5dff994e48f2d1ed05c14657c801
parentbd4668b9621c5cd3b7047eb050b5cef7b8221c32 (diff)
downloadedk2-platforms-3e11f7eb7174302bb350664e402552ea1bea399d.tar.xz
Enable Capsule update and ESRT feature. Several modules are modified or added for the feature.
git-svn-id: https://ssvn.intel.com:80/ssg/csd/tiano/tianoad/Research/Developer/mangguo/MinnowBoardMaxUDK2015Platform@106127 f973567a-9dae-4ef8-9d9d-80fbec5b6bbd # Conflicts: # Vlv2TbltDevicePkg/PlatformPkgConfig.dsc # Vlv2TbltDevicePkg/PlatformPkgIA32.dsc
-rw-r--r--Vlv2TbltDevicePkg/BiosUpdateConfig/BiosUpdateConfig.ini23
-rw-r--r--Vlv2TbltDevicePkg/FmpSample/FmpSample.c114
-rw-r--r--Vlv2TbltDevicePkg/FmpSample/FmpSample.h177
-rw-r--r--Vlv2TbltDevicePkg/FmpSample/FmpSample.inf64
-rw-r--r--Vlv2TbltDevicePkg/FmpSample/FmpSampleImpl.c336
-rw-r--r--Vlv2TbltDevicePkg/FvbRuntimeDxe/FvbRuntimeDxe.inf4
-rw-r--r--Vlv2TbltDevicePkg/FvbRuntimeDxe/FvbService.c37
-rw-r--r--Vlv2TbltDevicePkg/FvbRuntimeDxe/FvbService.h2
-rw-r--r--Vlv2TbltDevicePkg/FvbRuntimeDxe/FvbSmm.inf4
-rw-r--r--Vlv2TbltDevicePkg/Include/Guid/FmpSampleImageInfoGuid.h30
-rw-r--r--Vlv2TbltDevicePkg/Include/Guid/SystemFwClassGuid.h30
-rw-r--r--Vlv2TbltDevicePkg/Library/DxeEsrtCapsuleBsLib/DxeCapsuleLib.c957
-rw-r--r--Vlv2TbltDevicePkg/Library/DxeEsrtCapsuleBsLib/DxeEsrtCapsuleBsLib.inf62
-rw-r--r--Vlv2TbltDevicePkg/Library/DxeEsrtCapsuleRtLib/DxeCapsuleLib.c1038
-rw-r--r--Vlv2TbltDevicePkg/Library/DxeEsrtCapsuleRtLib/DxeEsrtCapsuleRtLib.inf64
-rw-r--r--Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLib.c4
-rw-r--r--Vlv2TbltDevicePkg/Library/FlashDeviceLib/SpiChipDefinitions.h2
-rw-r--r--Vlv2TbltDevicePkg/Library/PlatformBdsLib/BdsPlatform.c59
-rw-r--r--Vlv2TbltDevicePkg/Library/PlatformBdsLib/BdsPlatform.h24
-rw-r--r--Vlv2TbltDevicePkg/Library/PlatformBdsLib/Capsules.c304
-rw-r--r--Vlv2TbltDevicePkg/Library/PlatformBdsLib/PlatformBdsLib.inf6
-rw-r--r--Vlv2TbltDevicePkg/PlatformEsrt/PlatformEsrtDxe.c140
-rw-r--r--Vlv2TbltDevicePkg/PlatformEsrt/PlatformEsrtDxe.h32
-rw-r--r--Vlv2TbltDevicePkg/PlatformEsrt/PlatformEsrtDxe.inf58
-rw-r--r--Vlv2TbltDevicePkg/PlatformPkg.dec12
-rw-r--r--Vlv2TbltDevicePkg/PlatformPkg.fdf67
-rw-r--r--Vlv2TbltDevicePkg/PlatformPkgConfig.dsc195
-rw-r--r--Vlv2TbltDevicePkg/PlatformPkgGcc.fdf55
-rw-r--r--Vlv2TbltDevicePkg/PlatformPkgGccX64.dsc48
-rw-r--r--Vlv2TbltDevicePkg/PlatformPkgIA32.dsc58
-rw-r--r--Vlv2TbltDevicePkg/PlatformPkgX64.dsc55
-rw-r--r--Vlv2TbltDevicePkg/UpdateDriverDxe/FlashUpdate.c1217
-rw-r--r--Vlv2TbltDevicePkg/UpdateDriverDxe/ParseUpdateProfile.c1134
-rw-r--r--Vlv2TbltDevicePkg/UpdateDriverDxe/UpdateDispatcher.c897
-rw-r--r--Vlv2TbltDevicePkg/UpdateDriverDxe/UpdateDriver.h217
-rw-r--r--Vlv2TbltDevicePkg/UpdateDriverDxe/UpdateDriverDxe.inf82
-rw-r--r--Vlv2TbltDevicePkg/UpdateDriverDxe/UpdateDriverDxe.unibin0 -> 1948 bytes
-rw-r--r--Vlv2TbltDevicePkg/UpdateDriverDxe/UpdateStrings.unibin0 -> 2400 bytes
38 files changed, 7455 insertions, 153 deletions
diff --git a/Vlv2TbltDevicePkg/BiosUpdateConfig/BiosUpdateConfig.ini b/Vlv2TbltDevicePkg/BiosUpdateConfig/BiosUpdateConfig.ini
new file mode 100644
index 0000000000..b867c19c85
--- /dev/null
+++ b/Vlv2TbltDevicePkg/BiosUpdateConfig/BiosUpdateConfig.ini
@@ -0,0 +1,23 @@
+/** @file
+
+ Copyright (c) 2004 - 2016, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ 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 = 1
+Update0 = FvMain
+
+[FvMain]
+UpdateType = 0 # Spi Update
+FvBaseAddress = 0xFFD10000 #FvImage base address
+FileGuid = 4A538818-5AE0-4eb2-B2EB-488B23657022
+FaultTolerant = FALSE \ No newline at end of file
diff --git a/Vlv2TbltDevicePkg/FmpSample/FmpSample.c b/Vlv2TbltDevicePkg/FmpSample/FmpSample.c
new file mode 100644
index 0000000000..77ffaaf0a1
--- /dev/null
+++ b/Vlv2TbltDevicePkg/FmpSample/FmpSample.c
@@ -0,0 +1,114 @@
+/** @file
+ Implement updatable firmware resource for Fmp Sample
+
+ Copyright (c) 2004 - 2016, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ 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 "FmpSample.h"
+
+//
+// FmpSample driver private data
+//
+FMP_SAMPLE_PRIVATE_DATA *mFmpSamplePrivate = NULL;
+
+
+EFI_FIRMWARE_MANAGEMENT_PROTOCOL mFirmwareManagementProtocol = {
+ FmpGetImageInfo,
+ FmpGetImage,
+ FmpSetImage,
+ FmpCheckImage,
+ FmpGetPackageInfo,
+ FmpSetPackageInfo
+};
+
+
+EFI_STATUS
+EFIAPI
+FmpSampleMain (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Initialize LanMacPrivateData
+ //
+ mFmpSamplePrivate = AllocateZeroPool (sizeof(FMP_SAMPLE_PRIVATE_DATA));
+ if (mFmpSamplePrivate == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Status = InitializePrivateData(mFmpSamplePrivate);
+ if (EFI_ERROR(Status)) {
+ FreePool(mFmpSamplePrivate);
+ mFmpSamplePrivate = NULL;
+ }
+
+ //
+ // Install FMP protocol.
+ //
+ Status = gBS->InstallProtocolInterface (
+ &mFmpSamplePrivate->Handle,
+ &gEfiFirmwareManagementProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &mFmpSamplePrivate->Fmp
+ );
+ if (EFI_ERROR (Status)) {
+ FreePool(mFmpSamplePrivate);
+ mFmpSamplePrivate = NULL;
+ return Status;
+ }
+
+ return Status;
+}
+
+
+/**
+ This is the default unload handle for FmpSample drivers
+
+ Update driver does not open virtual handler by driver. So can not use
+ Disconnect to call DriverBinding stop. Here we directly uninstall FMP
+ and free resource
+
+ @param[in] ImageHandle The drivers' driver image.
+
+ @retval EFI_SUCCESS The image is unloaded.
+ @retval Others Failed to unload the image.
+
+**/
+EFI_STATUS
+EFIAPI
+FmpSampleUnload (
+ IN EFI_HANDLE ImageHandle
+ )
+{
+ //
+ // If the driver has been connected
+ //
+ if (mFmpSamplePrivate != NULL) {
+ //
+ // Uninstall FMP protocol
+ //
+ gBS->UninstallMultipleProtocolInterfaces(
+ mFmpSamplePrivate->Handle,
+ &gEfiFirmwareManagementProtocolGuid,
+ &mFmpSamplePrivate->Fmp,
+ NULL
+ );
+
+ FreePool(mFmpSamplePrivate);
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/Vlv2TbltDevicePkg/FmpSample/FmpSample.h b/Vlv2TbltDevicePkg/FmpSample/FmpSample.h
new file mode 100644
index 0000000000..8a9589f12b
--- /dev/null
+++ b/Vlv2TbltDevicePkg/FmpSample/FmpSample.h
@@ -0,0 +1,177 @@
+/** @file
+ FmpSample header file
+
+ Copyright (c) 2004 - 2016, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _FMP_SAMPLE_UPDATE_H_
+#define _FMP_SAMPLE_UPDATE_H_
+
+#include <PiDxe.h>
+
+#include <Guid/SystemResourceTable.h>
+#include <Guid/FmpSampleImageInfoGuid.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>
+
+//
+// Current Firmwarre version
+//
+#define CURRENT_FIRMWARE_VERSION 0x00000001
+//
+// The lowesest Supported Firmware Version
+//
+#define LOWEST_SUPPORTED_FIRMWARE_VERSION 0x00000001
+
+
+//
+// Image Version number
+//
+
+#define FMP_SAMPLE_PRIVATE_DATA_SIGNATURE SIGNATURE_32('F', 'M', 'P', 'S')
+
+#pragma pack(1)
+typedef struct{
+ UINT32 Version;
+ UINT32 Data;
+}FMP_SAMPLE_UDPATE_DATA;
+#pragma pack()
+
+//
+// LAN MAC private data structure.
+//
+struct _FMP_SAMPLE_PRIVATE_DATA{
+ UINT32 Signature;
+ EFI_FIRMWARE_MANAGEMENT_PROTOCOL Fmp;
+ EFI_HANDLE Handle;
+ UINT8 DescriptorCount;
+ EFI_SYSTEM_RESOURCE_ENTRY EsrtInfo;
+ FMP_SAMPLE_UDPATE_DATA UpdateData;
+};
+
+typedef struct _FMP_SAMPLE_PRIVATE_DATA FMP_SAMPLE_PRIVATE_DATA;
+
+
+/**
+ Returns a pointer to the FMP_SAMPLE_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 FMP_SAMPLE_PRIVATE_DATA.
+
+**/
+#define FMP_SAMPLE_PRIVATE_DATA_FROM_FMP(a) \
+ CR ( \
+ (a), \
+ FMP_SAMPLE_PRIVATE_DATA, \
+ Fmp, \
+ FMP_SAMPLE_PRIVATE_DATA_SIGNATURE \
+ )
+
+
+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
+ );
+
+EFI_STATUS
+EFIAPI FmpGetImage(
+ IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This,
+ IN UINT8 ImageIndex,
+ IN OUT VOID *Image,
+ IN OUT UINTN *ImageSize
+ );
+
+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
+EFIAPI FmpCheckImage(
+ IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This,
+ IN UINT8 ImageIndex,
+ IN CONST VOID *Image,
+ IN UINTN ImageSize,
+ OUT UINT32 *ImageUpdatable
+ );
+
+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
+ );
+
+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
+ );
+
+/*++
+
+ Routine Description:
+
+ Initialize FmpSampleDriver private data structure.
+
+ Arguments:
+
+
+ FmpSamplePrivate - private data structure to be initialized.
+
+ Returns:
+
+ --*/
+EFI_STATUS
+InitializePrivateData(
+ IN FMP_SAMPLE_PRIVATE_DATA *FmpSamplePrivate
+ );
+
+extern EFI_FIRMWARE_MANAGEMENT_PROTOCOL mFirmwareManagementProtocol;
+
+#endif
+
diff --git a/Vlv2TbltDevicePkg/FmpSample/FmpSample.inf b/Vlv2TbltDevicePkg/FmpSample/FmpSample.inf
new file mode 100644
index 0000000000..ac7114a9ef
--- /dev/null
+++ b/Vlv2TbltDevicePkg/FmpSample/FmpSample.inf
@@ -0,0 +1,64 @@
+## @file
+# Component description file for FmpSample module
+#
+#
+# Copyright (c) 2004 - 2016, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# 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 = FmpSample
+ FILE_GUID = 30743C10-6706-4E45-9722-EC7FB6D2161D
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = FmpSampleMain
+ UNLOAD_IMAGE = FmpSampleUnload
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = X64
+#
+
+[Sources]
+ FmpSample.c
+ FmpSampleImpl.c
+ FmpSample.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ Vlv2TbltDevicePkg/PlatformPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ UefiLib
+ BaseMemoryLib
+ DebugLib
+ PcdLib
+ MemoryAllocationLib
+ UefiBootServicesTableLib
+ HobLib
+ UefiRuntimeServicesTableLib
+ UefiDriverEntryPoint
+
+[Guids]
+ gFMPSampleUpdateImageInfoGuid
+
+[Protocols]
+ gEfiFirmwareManagementProtocolGuid ## SOMTIMES_PRODUCE
+
+[Pcd]
+
+[FixedPcd]
+
+[Depex]
+ gEfiVariableWriteArchProtocolGuid \ No newline at end of file
diff --git a/Vlv2TbltDevicePkg/FmpSample/FmpSampleImpl.c b/Vlv2TbltDevicePkg/FmpSample/FmpSampleImpl.c
new file mode 100644
index 0000000000..0ba0bedc1c
--- /dev/null
+++ b/Vlv2TbltDevicePkg/FmpSample/FmpSampleImpl.c
@@ -0,0 +1,336 @@
+/** @file
+ Implement updatable firmware resource for Fmp Sample
+
+ Copyright (c) 1999 - 2015, Intel Corporation. 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 "FmpSample.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
+ )
+{
+ FMP_SAMPLE_PRIVATE_DATA *FmpSamplePrivate;
+
+ if(ImageInfoSize == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (*ImageInfoSize < sizeof(EFI_FIRMWARE_IMAGE_DESCRIPTOR)) {
+ *ImageInfoSize = sizeof(EFI_FIRMWARE_IMAGE_DESCRIPTOR);
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ if (ImageInfo == NULL
+ || DescriptorVersion == NULL
+ || DescriptorCount == NULL
+ || DescriptorSize == NULL
+ || PackageVersion == NULL
+ || PackageVersionName == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ FmpSamplePrivate = FMP_SAMPLE_PRIVATE_DATA_FROM_FMP(This);
+
+ *ImageInfoSize = sizeof(EFI_FIRMWARE_IMAGE_DESCRIPTOR) * FmpSamplePrivate->DescriptorCount;
+ *DescriptorSize = sizeof(EFI_FIRMWARE_IMAGE_DESCRIPTOR);
+ *DescriptorCount = FmpSamplePrivate->DescriptorCount;
+ *DescriptorVersion = EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION;
+ //
+ // Do not support package version
+ //
+ *PackageVersion = 0xFFFFFFFF;
+ *PackageVersionName = NULL;
+
+ //
+ // LanMacUpdate supports 1 ImageInfo descriptor
+ //
+ ImageInfo[0].ImageIndex = 0x01;
+ ImageInfo[0].ImageTypeId = FmpSamplePrivate->EsrtInfo.FwClass;
+ ImageInfo[0].ImageId = 0x01;
+ ImageInfo[0].ImageIdName = NULL;
+ ImageInfo[0].VersionName = NULL;
+ ImageInfo[0].Size = sizeof(FmpSamplePrivate->UpdateData);
+ ImageInfo[0].AttributesSupported = IMAGE_ATTRIBUTE_IMAGE_UPDATABLE | IMAGE_ATTRIBUTE_RESET_REQUIRED | IMAGE_ATTRIBUTE_IN_USE;
+ ImageInfo[0].AttributesSetting = IMAGE_ATTRIBUTE_IMAGE_UPDATABLE | IMAGE_ATTRIBUTE_RESET_REQUIRED | IMAGE_ATTRIBUTE_IN_USE;
+ ImageInfo[0].Compatibilities = 0x0;
+ ImageInfo[0].Version = FmpSamplePrivate->EsrtInfo.FwVersion;
+ ImageInfo[0].LowestSupportedImageVersion = FmpSamplePrivate->EsrtInfo.LowestSupportedFwVersion;
+ ImageInfo[0].LastAttemptVersion = FmpSamplePrivate->EsrtInfo.LastAttemptVersion;
+ ImageInfo[0].LastAttemptStatus = FmpSamplePrivate->EsrtInfo.LastAttemptStatus;
+ ImageInfo[0].HardwareInstance = 0;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI FmpGetImage(
+ IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This,
+ IN UINT8 ImageIndex,
+ IN OUT VOID *Image,
+ IN OUT UINTN *ImageSize
+ )
+{
+ FMP_SAMPLE_PRIVATE_DATA *FmpSamplePrivate;
+
+ if (Image == NULL || ImageSize == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ FmpSamplePrivate = FMP_SAMPLE_PRIVATE_DATA_FROM_FMP(This);
+
+ if (ImageIndex == 0 || ImageIndex > FmpSamplePrivate->DescriptorCount || ImageSize == NULL || Image == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (*ImageSize < sizeof(FmpSamplePrivate->UpdateData)) {
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ CopyMem(Image, &FmpSamplePrivate->UpdateData, sizeof(FmpSamplePrivate->UpdateData));
+ *ImageSize = sizeof(FmpSamplePrivate->UpdateData);
+
+ return EFI_SUCCESS;
+}
+
+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;
+ FMP_SAMPLE_PRIVATE_DATA *FmpSamplePrivate;
+
+ if (Image == NULL || AbortReason == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ FmpSamplePrivate = FMP_SAMPLE_PRIVATE_DATA_FROM_FMP(This);
+ *AbortReason = NULL;
+
+ if (ImageIndex == 0 || ImageIndex > FmpSamplePrivate->DescriptorCount || ImageSize != sizeof(FmpSamplePrivate->UpdateData) || Image == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Update Version in NV after successful flash image update .
+ //
+ Status = gRT->SetVariable(
+ L"UpdateData",
+ &gFMPSampleUpdateImageInfoGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
+ sizeof(FmpSamplePrivate->UpdateData),
+ (FMP_SAMPLE_UDPATE_DATA *)Image
+ );
+
+ FmpSamplePrivate->EsrtInfo.FwVersion = ((FMP_SAMPLE_UDPATE_DATA *)Image)->Version;
+ FmpSamplePrivate->EsrtInfo.LastAttemptVersion = ((FMP_SAMPLE_UDPATE_DATA *)Image)->Version;
+ if (EFI_ERROR(Status)) {
+ FmpSamplePrivate->EsrtInfo.LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL;
+ } else {
+ FmpSamplePrivate->EsrtInfo.LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;
+ }
+
+ Status = gRT->SetVariable(
+ L"FmpInfo",
+ &gFMPSampleUpdateImageInfoGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
+ sizeof(FmpSamplePrivate->EsrtInfo),
+ &FmpSamplePrivate->EsrtInfo
+ );
+
+ return Status;
+}
+
+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;
+}
+
+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;
+}
+
+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;
+}
+
+/*++
+
+ Routine Description:
+
+ Initialize FmpSampleDriver private data structure.
+
+ Arguments:
+
+
+ FmpSamplePrivate - private data structure to be initialized.
+
+ Returns:
+
+ --*/
+EFI_STATUS
+InitializePrivateData(
+ IN FMP_SAMPLE_PRIVATE_DATA *FmpSamplePrivate
+ )
+{
+ EFI_STATUS Status;
+ EFI_BOOT_MODE BootMode;
+ UINTN DataSize;
+
+ //
+ // Get current Boot Mode
+ //
+ BootMode = GetBootModeHob ();
+
+ //
+ // The NV Variable is not available in RECOVERY Mode
+ //
+ if (BootMode == BOOT_IN_RECOVERY_MODE) {
+ return EFI_UNSUPPORTED;
+ }
+
+ FmpSamplePrivate->Signature = FMP_SAMPLE_PRIVATE_DATA_SIGNATURE;
+ FmpSamplePrivate->Handle = NULL;
+ FmpSamplePrivate->DescriptorCount = 1;
+ CopyMem(&FmpSamplePrivate->Fmp, &mFirmwareManagementProtocol, sizeof(EFI_FIRMWARE_MANAGEMENT_PROTOCOL));
+
+ DataSize = sizeof(FmpSamplePrivate->EsrtInfo);
+ Status = gRT->GetVariable(
+ L"FmpInfo",
+ &gFMPSampleUpdateImageInfoGuid,
+ NULL,
+ &DataSize,
+ &FmpSamplePrivate->EsrtInfo
+ );
+
+ if (EFI_ERROR(Status)) {
+ FmpSamplePrivate->EsrtInfo.CapsuleFlags = 0;
+ FmpSamplePrivate->EsrtInfo.FwClass = gFMPSampleUpdateImageInfoGuid;
+ FmpSamplePrivate->EsrtInfo.FwType = ESRT_FW_TYPE_DEVICEFIRMWARE;
+ FmpSamplePrivate->EsrtInfo.FwVersion = CURRENT_FIRMWARE_VERSION;
+ FmpSamplePrivate->EsrtInfo.LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;
+ FmpSamplePrivate->EsrtInfo.LastAttemptVersion = 0;
+ FmpSamplePrivate->EsrtInfo.LowestSupportedFwVersion = LOWEST_SUPPORTED_FIRMWARE_VERSION;
+ Status = gRT->SetVariable(
+ L"FmpInfo",
+ &gFMPSampleUpdateImageInfoGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
+ sizeof(FmpSamplePrivate->EsrtInfo),
+ &FmpSamplePrivate->EsrtInfo
+ );
+
+ } else if (DataSize != sizeof(FmpSamplePrivate->EsrtInfo)) {
+ Status = EFI_INVALID_PARAMETER;
+ }
+
+ DataSize = sizeof(FmpSamplePrivate->UpdateData);
+ Status = gRT->GetVariable(
+ L"UpdateData",
+ &gFMPSampleUpdateImageInfoGuid,
+ NULL,
+ &DataSize,
+ &FmpSamplePrivate->UpdateData
+ );
+
+ if (EFI_ERROR(Status)) {
+ FmpSamplePrivate->UpdateData.Version = 0;
+ FmpSamplePrivate->UpdateData.Data = 0;
+
+ Status = gRT->SetVariable(
+ L"UpdateData",
+ &gFMPSampleUpdateImageInfoGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
+ sizeof(FmpSamplePrivate->UpdateData),
+ &FmpSamplePrivate->UpdateData
+ );
+ }
+ return Status;
+}
+
diff --git a/Vlv2TbltDevicePkg/FvbRuntimeDxe/FvbRuntimeDxe.inf b/Vlv2TbltDevicePkg/FvbRuntimeDxe/FvbRuntimeDxe.inf
index e8e6411fe4..dce1d8755b 100644
--- a/Vlv2TbltDevicePkg/FvbRuntimeDxe/FvbRuntimeDxe.inf
+++ b/Vlv2TbltDevicePkg/FvbRuntimeDxe/FvbRuntimeDxe.inf
@@ -57,6 +57,7 @@
UefiRuntimeLib
UefiBootServicesTableLib
UefiDriverEntryPoint
+ HobLib
[Guids]
gEfiFirmwareFileSystem2Guid # ALWAYS_CONSUMED
@@ -71,6 +72,9 @@
gPlatformModuleTokenSpaceGuid.PcdFlashFvMainBase
gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase
gPlatformModuleTokenSpaceGuid.PcdFlashFvRecoveryBase
+
+[FeaturePcd]
+ gPlatformModuleTokenSpaceGuid.PcdFeatureRecoveryDisabled
[Pcd]
gPlatformModuleTokenSpaceGuid.PcdFlashFvMainSize
diff --git a/Vlv2TbltDevicePkg/FvbRuntimeDxe/FvbService.c b/Vlv2TbltDevicePkg/FvbRuntimeDxe/FvbService.c
index da7dce6e13..723728ad65 100644
--- a/Vlv2TbltDevicePkg/FvbRuntimeDxe/FvbService.c
+++ b/Vlv2TbltDevicePkg/FvbRuntimeDxe/FvbService.c
@@ -1017,13 +1017,42 @@ FvbInitialize (
UINTN Idx;
UINT32 MaxLbaSize;
BOOLEAN FvHeaderValid;
+EFI_BOOT_MODE BootMode;
+UINT32 PlatformFvBaseAddress[2];
+UINT32 PlatformFvBaseAddressCount;
+UINT32 PlatformFvLockList[3];
+UINT32 PlatformFvLockListCount;
+ //
+ // This platform driver knows there are 3 FVs on
+ // FD, which are FvRecovery, FvMain and FvNvStorage.
+ //
+ BootMode = GetBootModeHob ();
+ if ( FeaturePcdGet ( PcdFeatureRecoveryDisabled ) || BootMode == BOOT_IN_RECOVERY_MODE) {
+ //
+ // On recovery boot, don't report any firmware FV images, because their data can't be trusted.
+ //
+ PlatformFvBaseAddressCount = 1;
+ PlatformFvBaseAddress[0] = PcdGet32 (PcdFlashNvStorageVariableBase);
+ } else {
+ PlatformFvBaseAddressCount = 2;
+ PlatformFvBaseAddress[0] = PcdGet32 (PcdFlashFvMainBase);
+ PlatformFvBaseAddress[1] = PcdGet32 (PcdFlashNvStorageVariableBase);
+ PlatformFvBaseAddress[2] = PcdGet32 (PcdFlashFvRecoveryBase);
+ }
+
+ //
+ // List of FVs that should be write protected on normal boots.
+ //
+ PlatformFvLockListCount = 1;
+ PlatformFvLockList[0] = PcdGet32 (PcdFlashFvMainBase);
+ PlatformFvLockList[1] = PcdGet32 (PcdFlashFvRecoveryBase);
//
// Calculate the total size for all firmware volume block instances.
//
BufferSize = 0;
- for (Idx = 0; Idx < 1; Idx++) {
- FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) mPlatformFvBaseAddress[Idx];
+ for (Idx = 0; Idx < PlatformFvBaseAddressCount; Idx++) {
+ FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) PlatformFvBaseAddress[Idx];
BufferSize += (FvHeader->HeaderLength +
sizeof (EFI_FW_VOL_INSTANCE) -
sizeof (EFI_FIRMWARE_VOLUME_HEADER)
@@ -1038,8 +1067,8 @@ FvbInitialize (
FwhInstance = mFvbModuleGlobal.FvInstance;
mFvbModuleGlobal.NumFv = 0;
- for (Idx = 0; Idx < 1; Idx++) {
- BaseAddress = mPlatformFvBaseAddress[Idx];
+ for (Idx = 0; Idx < PlatformFvBaseAddressCount; Idx++) {
+ BaseAddress = PlatformFvBaseAddress[Idx];
FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) BaseAddress;
if (!IsFvHeaderValid (BaseAddress, FwVolHeader)) {
diff --git a/Vlv2TbltDevicePkg/FvbRuntimeDxe/FvbService.h b/Vlv2TbltDevicePkg/FvbRuntimeDxe/FvbService.h
index cfdb92c5bc..9ace55d035 100644
--- a/Vlv2TbltDevicePkg/FvbRuntimeDxe/FvbService.h
+++ b/Vlv2TbltDevicePkg/FvbRuntimeDxe/FvbService.h
@@ -25,6 +25,7 @@ Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
#include <Library/UefiDriverEntryPoint.h>
#include <Library/UefiBootServicesTableLib.h>
+#include <Library/BaseLib.h>
#include <Library/UefiLib.h>
#include <Library/BaseLib.h>
#include <Library/DebugLib.h>
@@ -35,6 +36,7 @@ Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
#include <Library/PcdLib.h>
#include <Library/FlashDeviceLib.h>
#include <Library/DevicePathLib.h>
+#include <Library/HobLib.h>
//
// Define two helper macro to extract the Capability field or Status field in FVB
diff --git a/Vlv2TbltDevicePkg/FvbRuntimeDxe/FvbSmm.inf b/Vlv2TbltDevicePkg/FvbRuntimeDxe/FvbSmm.inf
index 718ae0bbb2..f61a4210eb 100644
--- a/Vlv2TbltDevicePkg/FvbRuntimeDxe/FvbSmm.inf
+++ b/Vlv2TbltDevicePkg/FvbRuntimeDxe/FvbSmm.inf
@@ -60,6 +60,7 @@
SmmServicesTableLib
UefiBootServicesTableLib
UefiDriverEntryPoint
+ HobLib
[Guids]
gEfiFirmwareFileSystem2Guid # ALWAYS_CONSUMED
@@ -74,6 +75,9 @@
gPlatformModuleTokenSpaceGuid.PcdFlashFvMainBase
gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase
gPlatformModuleTokenSpaceGuid.PcdFlashFvRecoveryBase
+
+[FeaturePcd]
+ gPlatformModuleTokenSpaceGuid.PcdFeatureRecoveryDisabled
[Pcd]
gPlatformModuleTokenSpaceGuid.PcdFlashFvMainSize
diff --git a/Vlv2TbltDevicePkg/Include/Guid/FmpSampleImageInfoGuid.h b/Vlv2TbltDevicePkg/Include/Guid/FmpSampleImageInfoGuid.h
new file mode 100644
index 0000000000..66cd56c7a0
--- /dev/null
+++ b/Vlv2TbltDevicePkg/Include/Guid/FmpSampleImageInfoGuid.h
@@ -0,0 +1,30 @@
+/** @file
+ FMP Sample updatable resource guid
+
+ Copyright (c) 2004 - 2016, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ 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>
+
+#ifndef _FMP_SAMPLE_UPDATE_IMAGE_INFO_GUID_H_
+#define _FMP_SAMPLE_UPDATE_IMAGE_INFO_GUID_H_
+
+//
+// GUID definition for FMP sample ImageInfo
+//
+#define FMP_SAMPLE_UPDATE_IMAGE_INFO_GUID \
+ { \
+ 0xb9847c4e, 0xf5b6, 0x42dc, { 0xb6, 0xf4, 0xed, 0x44, 0x7, 0xb0, 0x67, 0x4c } \
+ }
+
+extern EFI_GUID gFMPSampleUpdateImageInfoGuid;
+#endif
diff --git a/Vlv2TbltDevicePkg/Include/Guid/SystemFwClassGuid.h b/Vlv2TbltDevicePkg/Include/Guid/SystemFwClassGuid.h
new file mode 100644
index 0000000000..6cfb7e7f05
--- /dev/null
+++ b/Vlv2TbltDevicePkg/Include/Guid/SystemFwClassGuid.h
@@ -0,0 +1,30 @@
+/** @file
+ System FW Class guid
+
+ Copyright (c) 2013 - 2015, Intel Corporation. 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>
+
+#ifndef _SYSTEM_FW_CLASS_GUID_H_
+#define _SYSTEM_FW_CLASS_GUID_H_
+
+//
+// GUID definition for System FW Class
+//
+#define SYSTEM_FW_CLASS_GUID \
+ { \
+ 0x819b858e, 0xc52c, 0x402f, { 0x80, 0xe1, 0x5b, 0x31, 0x1b, 0x6c, 0x19, 0x59 }\
+ }
+
+extern EFI_GUID gSystemFwClassGuid;
+#endif
diff --git a/Vlv2TbltDevicePkg/Library/DxeEsrtCapsuleBsLib/DxeCapsuleLib.c b/Vlv2TbltDevicePkg/Library/DxeEsrtCapsuleBsLib/DxeCapsuleLib.c
new file mode 100644
index 0000000000..4b1acb40ec
--- /dev/null
+++ b/Vlv2TbltDevicePkg/Library/DxeEsrtCapsuleBsLib/DxeCapsuleLib.c
@@ -0,0 +1,957 @@
+/** @file
+ Capsule Boottime Library instance to update capsule image to flash.
+
+ Copyright (c) 2004 - 2016, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+
+#include <PiDxe.h>
+
+#include <IndustryStandard/Bmp.h>
+#include <IndustryStandard/WindowsUxCapsule.h>
+
+#include <Guid/FmpCapsule.h>
+#include <Guid/Capsule.h>
+#include <Guid/SystemResourceTable.h>
+
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/CapsuleLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/UefiBootManagerLib.h>
+
+#include <Protocol/GraphicsOutput.h>
+#include <Protocol/EsrtManagement.h>
+#include <Protocol/FirmwareManagement.h>
+#include <Protocol/DevicePath.h>
+
+
+/**
+ Function indicate the current completion progress of the firmware
+ update. Platform may override with own specific progress function.
+
+ @param Completion A value between 1 and 100 indicating the current completion progress of the firmware update
+
+ @retval EFI_SUCESS Input capsule is a correct FMP capsule.
+**/
+EFI_STATUS
+EFIAPI
+Update_Image_Progress (
+ IN UINTN Completion
+)
+{
+ return EFI_SUCCESS;
+}
+
+/**
+ Validate Fmp capsules layout.
+
+ @param CapsuleHeader Points to a capsule header.
+
+ @retval EFI_SUCESS Input capsule is a correct FMP capsule.
+ @retval EFI_INVALID_PARAMETER Input capsule is not a correct FMP capsule.
+**/
+EFI_STATUS
+ValidateFmpCapsule (
+ IN EFI_CAPSULE_HEADER *CapsuleHeader
+ )
+{
+ EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *FmpCapsuleHeader;
+ UINT8 *EndOfCapsule;
+ EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader;
+ UINT8 *EndOfPayload;
+ UINT64 *ItemOffsetList;
+ UINT32 ItemNum;
+ UINTN Index;
+
+ FmpCapsuleHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *) ((UINT8 *) CapsuleHeader + CapsuleHeader->HeaderSize);
+ EndOfCapsule = (UINT8 *) CapsuleHeader + CapsuleHeader->CapsuleImageSize;
+
+ if (FmpCapsuleHeader->Version > EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION) {
+ return EFI_INVALID_PARAMETER;
+ }
+ ItemOffsetList = (UINT64 *)(FmpCapsuleHeader + 1);
+
+ ItemNum = FmpCapsuleHeader->EmbeddedDriverCount + FmpCapsuleHeader->PayloadItemCount;
+
+ if (ItemNum == FmpCapsuleHeader->EmbeddedDriverCount) {
+ //
+ // No payload element
+ //
+ if (((UINT8 *)FmpCapsuleHeader + ItemOffsetList[ItemNum - 1]) < EndOfCapsule) {
+ return EFI_SUCCESS;
+ } else {
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ if (FmpCapsuleHeader->PayloadItemCount != 0) {
+ //
+ // Check if the last payload is within capsule image range
+ //
+ ImageHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *)((UINT8 *)FmpCapsuleHeader + ItemOffsetList[ItemNum - 1]);
+ EndOfPayload = (UINT8 *)(ImageHeader + 1) + ImageHeader->UpdateImageSize + ImageHeader->UpdateVendorCodeSize;
+ } else {
+ //
+ // No driver & payload element in FMP
+ //
+ EndOfPayload = (UINT8 *)(FmpCapsuleHeader + 1);
+ }
+
+ if (EndOfPayload != EndOfCapsule) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // All the address in ItemOffsetList must be stored in ascending order
+ //
+ if (ItemNum >= 2) {
+ for (Index = 0; Index < ItemNum - 1; Index++) {
+ if (ItemOffsetList[Index] >= ItemOffsetList[Index + 1]) {
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Convert a *.BMP graphics image to a GOP blt buffer. If a NULL Blt buffer
+ is passed in a GopBlt buffer will be allocated by this routine. If a GopBlt
+ buffer is passed in it will be used if it is big enough.
+
+ @param BmpImage Pointer to BMP file
+ @param BmpImageSize Number of bytes in BmpImage
+ @param GopBlt Buffer containing GOP version of BmpImage.
+ @param GopBltSize Size of GopBlt in bytes.
+ @param PixelHeight Height of GopBlt/BmpImage in pixels
+ @param PixelWidth Width of GopBlt/BmpImage in pixels
+
+ @retval EFI_SUCCESS GopBlt and GopBltSize are returned.
+ @retval EFI_UNSUPPORTED BmpImage is not a valid *.BMP image
+ @retval EFI_BUFFER_TOO_SMALL The passed in GopBlt buffer is not big enough.
+ GopBltSize will contain the required size.
+ @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate.
+
+**/
+static
+EFI_STATUS
+ConvertBmpToGopBlt (
+ IN VOID *BmpImage,
+ IN UINTN BmpImageSize,
+ IN OUT VOID **GopBlt,
+ IN OUT UINTN *GopBltSize,
+ OUT UINTN *PixelHeight,
+ OUT UINTN *PixelWidth
+ )
+{
+ UINT8 *Image;
+ UINT8 *ImageHeader;
+ BMP_IMAGE_HEADER *BmpHeader;
+ BMP_COLOR_MAP *BmpColorMap;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;
+ UINT64 BltBufferSize;
+ UINTN Index;
+ UINTN Height;
+ UINTN Width;
+ UINTN ImageIndex;
+ BOOLEAN IsAllocated;
+
+ BmpHeader = (BMP_IMAGE_HEADER *) BmpImage;
+
+ if (BmpHeader->CharB != 'B' || BmpHeader->CharM != 'M') {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Doesn't support compress.
+ //
+ if (BmpHeader->CompressionType != 0) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Calculate Color Map offset in the image.
+ //
+ Image = BmpImage;
+ BmpColorMap = (BMP_COLOR_MAP *) (Image + sizeof (BMP_IMAGE_HEADER));
+
+ //
+ // Calculate graphics image data address in the image
+ //
+ Image = ((UINT8 *) BmpImage) + BmpHeader->ImageOffset;
+ ImageHeader = Image;
+
+ //
+ // Calculate the BltBuffer needed size.
+ //
+ BltBufferSize = MultU64x32 ((UINT64) BmpHeader->PixelWidth, BmpHeader->PixelHeight);
+ //
+ // Ensure the BltBufferSize * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) doesn't overflow
+ //
+ if (BltBufferSize > DivU64x32 ((UINTN) ~0, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL))) {
+ return EFI_UNSUPPORTED;
+ }
+ BltBufferSize = MultU64x32 (BltBufferSize, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
+
+ IsAllocated = FALSE;
+ if (*GopBlt == NULL) {
+ //
+ // GopBlt is not allocated by caller.
+ //
+ *GopBltSize = (UINTN) BltBufferSize;
+ *GopBlt = AllocatePool (*GopBltSize);
+ IsAllocated = TRUE;
+ if (*GopBlt == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ } else {
+ //
+ // GopBlt has been allocated by caller.
+ //
+ if (*GopBltSize < (UINTN) BltBufferSize) {
+ *GopBltSize = (UINTN) BltBufferSize;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+ }
+
+ *PixelWidth = BmpHeader->PixelWidth;
+ *PixelHeight = BmpHeader->PixelHeight;
+
+ //
+ // Convert image from BMP to Blt buffer format
+ //
+ BltBuffer = *GopBlt;
+ for (Height = 0; Height < BmpHeader->PixelHeight; Height++) {
+ Blt = &BltBuffer[(BmpHeader->PixelHeight - Height - 1) * BmpHeader->PixelWidth];
+ for (Width = 0; Width < BmpHeader->PixelWidth; Width++, Image++, Blt++) {
+ switch (BmpHeader->BitPerPixel) {
+ case 1:
+ //
+ // Convert 1-bit (2 colors) BMP to 24-bit color
+ //
+ for (Index = 0; Index < 8 && Width < BmpHeader->PixelWidth; Index++) {
+ Blt->Red = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Red;
+ Blt->Green = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Green;
+ Blt->Blue = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Blue;
+ Blt++;
+ Width++;
+ }
+
+ Blt--;
+ Width--;
+ break;
+
+ case 4:
+ //
+ // Convert 4-bit (16 colors) BMP Palette to 24-bit color
+ //
+ Index = (*Image) >> 4;
+ Blt->Red = BmpColorMap[Index].Red;
+ Blt->Green = BmpColorMap[Index].Green;
+ Blt->Blue = BmpColorMap[Index].Blue;
+ if (Width < (BmpHeader->PixelWidth - 1)) {
+ Blt++;
+ Width++;
+ Index = (*Image) & 0x0f;
+ Blt->Red = BmpColorMap[Index].Red;
+ Blt->Green = BmpColorMap[Index].Green;
+ Blt->Blue = BmpColorMap[Index].Blue;
+ }
+ break;
+
+ case 8:
+ //
+ // Convert 8-bit (256 colors) BMP Palette to 24-bit color
+ //
+ Blt->Red = BmpColorMap[*Image].Red;
+ Blt->Green = BmpColorMap[*Image].Green;
+ Blt->Blue = BmpColorMap[*Image].Blue;
+ break;
+
+ case 24:
+ //
+ // It is 24-bit BMP.
+ //
+ Blt->Blue = *Image++;
+ Blt->Green = *Image++;
+ Blt->Red = *Image;
+ break;
+
+ case 32:
+ //
+ // it is 32-bit BMP. Skip pixel's highest byte
+ //
+ Blt->Blue = *Image++;
+ Blt->Green = *Image++;
+ Blt->Red = *Image++;
+ break;
+
+ default:
+ //
+ // Other bit format BMP is not supported.
+ //
+ if (IsAllocated) {
+ FreePool (*GopBlt);
+ *GopBlt = NULL;
+ }
+ return EFI_UNSUPPORTED;
+ break;
+ };
+
+ }
+
+ ImageIndex = (UINTN) (Image - ImageHeader);
+ if ((ImageIndex % 4) != 0) {
+ //
+ // Bmp Image starts each row on a 32-bit boundary!
+ //
+ Image = Image + (4 - (ImageIndex % 4));
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Those capsules supported by the firmwares.
+
+ @param CapsuleHeader Points to a capsule header.
+
+ @retval EFI_SUCESS Input capsule is supported by firmware.
+ @retval EFI_UNSUPPORTED Input capsule is not supported by the firmware.
+**/
+EFI_STATUS
+DisplayCapsuleImage (
+ IN DISPLAY_DISPLAY_PAYLOAD *ImagePayload,
+ IN UINTN PayloadSize
+ )
+{
+ EFI_STATUS Status;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;
+ UINTN BltSize;
+ UINTN Height;
+ UINTN Width;
+ EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
+
+ //
+ // Only Support Bitmap by now
+ //
+ if (ImagePayload->ImageType != 0) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Try to open GOP
+ //
+ Status = gBS->HandleProtocol (gST->ConsoleOutHandle, &gEfiGraphicsOutputProtocolGuid, (VOID **)&GraphicsOutput);
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ if (GraphicsOutput->Mode->Mode != ImagePayload->Mode) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Blt = NULL;
+ Width = 0;
+ Height = 0;
+ Status = ConvertBmpToGopBlt (
+ ImagePayload + 1,
+ PayloadSize - sizeof(DISPLAY_DISPLAY_PAYLOAD),
+ (VOID **)&Blt,
+ &BltSize,
+ &Height,
+ &Width
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = GraphicsOutput->Blt (
+ GraphicsOutput,
+ Blt,
+ EfiBltBufferToVideo,
+ 0,
+ 0,
+ (UINTN) ImagePayload->OffsetX,
+ (UINTN) ImagePayload->OffsetY,
+ Width,
+ Height,
+ Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
+ );
+
+ FreePool(Blt);
+
+ return Status;
+}
+
+/**
+ Process Firmware management protocol data capsule.
+
+ @param CapsuleHeader Points to a capsule header.
+
+ @retval EFI_SUCESS Process Capsule Image successfully.
+ @retval EFI_UNSUPPORTED Capsule image is not supported by the firmware.
+ @retval EFI_VOLUME_CORRUPTED FV volume in the capsule is corrupted.
+ @retval EFI_OUT_OF_RESOURCES Not enough memory.
+**/
+EFI_STATUS
+ProcessFmpCapsuleImage (
+ IN EFI_CAPSULE_HEADER *CapsuleHeader
+ )
+{
+ EFI_STATUS Status;
+ EFI_STATUS StatusEsrt;
+ EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *FmpCapsuleHeader;
+ UINT8 *EndOfCapsule;
+ EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader;
+ UINT8 *Image;
+ EFI_HANDLE ImageHandle;
+ UINT64 *ItemOffsetList;
+ UINT32 ItemNum;
+ UINTN Index;
+ UINTN ExitDataSize;
+ EFI_HANDLE *HandleBuffer;
+ EFI_FIRMWARE_MANAGEMENT_PROTOCOL *Fmp;
+ UINTN NumberOfHandles;
+ UINTN DescriptorSize;
+ UINT8 FmpImageInfoCount;
+ UINT32 FmpImageInfoDescriptorVer;
+ UINTN ImageInfoSize;
+ UINT32 PackageVersion;
+ CHAR16 *PackageVersionName;
+ CHAR16 *AbortReason;
+ EFI_FIRMWARE_IMAGE_DESCRIPTOR *FmpImageInfoBuf;
+ EFI_FIRMWARE_IMAGE_DESCRIPTOR *TempFmpImageInfo;
+ UINTN DriverLen;
+ UINTN Index1;
+ UINTN Index2;
+ MEMMAP_DEVICE_PATH MemMapNode;
+ EFI_DEVICE_PATH_PROTOCOL *DriverDevicePath;
+ ESRT_MANAGEMENT_PROTOCOL *EsrtProtocol;
+ EFI_SYSTEM_RESOURCE_ENTRY EsrtEntry;
+
+ Status = EFI_SUCCESS;
+ HandleBuffer = NULL;
+ ExitDataSize = 0;
+ DriverDevicePath = NULL;
+ EsrtProtocol = NULL;
+
+ FmpCapsuleHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *) ((UINT8 *) CapsuleHeader + CapsuleHeader->HeaderSize);
+ EndOfCapsule = (UINT8 *) CapsuleHeader + CapsuleHeader->CapsuleImageSize;
+
+ if (FmpCapsuleHeader->Version > EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION) {
+ return EFI_INVALID_PARAMETER;
+ }
+ ItemOffsetList = (UINT64 *)(FmpCapsuleHeader + 1);
+
+ ItemNum = FmpCapsuleHeader->EmbeddedDriverCount + FmpCapsuleHeader->PayloadItemCount;
+
+ //
+ // capsule in which driver count and payload count are both zero is not processed.
+ //
+ if (ItemNum == 0) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Update corresponding ESRT entry LastAttemp Status
+ //
+ Status = gBS->LocateProtocol(&gEsrtManagementProtocolGuid, NULL, (VOID **)&EsrtProtocol);
+
+ //
+ // 1. ConnectAll to ensure
+ // All the communication protocol required by driver in capsule installed
+ // All FMP protocols are installed
+ //
+ EfiBootManagerConnectAll();
+
+
+ //
+ // 2. Try to load & start all the drivers within capsule
+ //
+ SetDevicePathNodeLength (&MemMapNode.Header, sizeof (MemMapNode));
+ MemMapNode.Header.Type = HARDWARE_DEVICE_PATH;
+ MemMapNode.Header.SubType = HW_MEMMAP_DP;
+ MemMapNode.MemoryType = EfiBootServicesCode;
+ MemMapNode.StartingAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)CapsuleHeader;
+ MemMapNode.EndingAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)((UINT8 *)CapsuleHeader + CapsuleHeader->CapsuleImageSize - 1);
+
+ DriverDevicePath = AppendDevicePathNode (NULL, &MemMapNode.Header);
+ if (DriverDevicePath == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ for (Index = 0; Index < FmpCapsuleHeader->EmbeddedDriverCount; Index++) {
+ if (FmpCapsuleHeader->PayloadItemCount == 0 && Index == (UINTN)FmpCapsuleHeader->EmbeddedDriverCount - 1) {
+ //
+ // When driver is last element in the ItemOffsetList array, the driver size is calculated by reference CapsuleImageSize in EFI_CAPSULE_HEADER
+ //
+ DriverLen = CapsuleHeader->CapsuleImageSize - CapsuleHeader->HeaderSize - (UINTN)ItemOffsetList[Index];
+ } else {
+ DriverLen = (UINTN)ItemOffsetList[Index + 1] - (UINTN)ItemOffsetList[Index];
+ }
+
+ Status = gBS->LoadImage(
+ FALSE,
+ gImageHandle,
+ DriverDevicePath,
+ (UINT8 *)FmpCapsuleHeader + ItemOffsetList[Index],
+ DriverLen,
+ &ImageHandle
+ );
+ if (EFI_ERROR(Status)) {
+ goto EXIT;
+ }
+
+ Status = gBS->StartImage(
+ ImageHandle,
+ &ExitDataSize,
+ NULL
+ );
+ if (EFI_ERROR(Status)) {
+ DEBUG ((DEBUG_ERROR, "Driver Return Status = %r\n", Status));
+ goto EXIT;
+ }
+ }
+
+ //
+ // Connnect all again to connect drivers within capsule
+ //
+ if (FmpCapsuleHeader->EmbeddedDriverCount > 0) {
+ EfiBootManagerConnectAll();
+ }
+
+ //
+ // 3. Route payload to right FMP instance
+ //
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiFirmwareManagementProtocolGuid,
+ NULL,
+ &NumberOfHandles,
+ &HandleBuffer
+ );
+
+ if (!EFI_ERROR(Status)) {
+ for(Index1 = 0; Index1 < NumberOfHandles; Index1++) {
+ Status = gBS->HandleProtocol(
+ HandleBuffer[Index1],
+ &gEfiFirmwareManagementProtocolGuid,
+ (VOID **)&Fmp
+ );
+ if (EFI_ERROR(Status)) {
+ continue;
+ }
+
+ ImageInfoSize = 0;
+ Status = Fmp->GetImageInfo (
+ Fmp,
+ &ImageInfoSize,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ );
+ if (Status != EFI_BUFFER_TOO_SMALL) {
+ continue;
+ }
+
+ FmpImageInfoBuf = NULL;
+ FmpImageInfoBuf = AllocateZeroPool (ImageInfoSize);
+ if (FmpImageInfoBuf == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto EXIT;
+ }
+
+ PackageVersionName = NULL;
+ Status = Fmp->GetImageInfo (
+ Fmp,
+ &ImageInfoSize, // ImageInfoSize
+ FmpImageInfoBuf, // ImageInfo
+ &FmpImageInfoDescriptorVer, // DescriptorVersion
+ &FmpImageInfoCount, // DescriptorCount
+ &DescriptorSize, // DescriptorSize
+ &PackageVersion, // PackageVersion
+ &PackageVersionName // PackageVersionName
+ );
+
+ //
+ // If FMP GetInformation interface failed, skip this resource
+ //
+ if (EFI_ERROR(Status)) {
+ FreePool(FmpImageInfoBuf);
+ continue;
+ }
+
+ if (PackageVersionName != NULL) {
+ FreePool(PackageVersionName);
+ }
+
+ TempFmpImageInfo = FmpImageInfoBuf;
+ for (Index2 = 0; Index2 < FmpImageInfoCount; Index2++) {
+ //
+ // Check all the payload entry in capsule payload list
+ //
+ for (Index = FmpCapsuleHeader->EmbeddedDriverCount; Index < ItemNum; Index++) {
+ ImageHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *)((UINT8 *)FmpCapsuleHeader + ItemOffsetList[Index]);
+ if (CompareGuid(&ImageHeader->UpdateImageTypeId, &TempFmpImageInfo->ImageTypeId) &&
+ ImageHeader->UpdateImageIndex == TempFmpImageInfo->ImageIndex) {
+ AbortReason = NULL;
+ if (ImageHeader->Version >= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {
+ if(ImageHeader->UpdateHardwareInstance != 0){
+ //
+ // FMP Version is >=2 & UpdateHardwareInstance Skip 2 case
+ // 1. FMP Image info Version < 3
+ // 2. HardwareInstance doesn't match
+ //
+ if (FmpImageInfoDescriptorVer < EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION ||
+ ImageHeader->UpdateHardwareInstance != TempFmpImageInfo->HardwareInstance) {
+ continue;
+ }
+ }
+ Image = (UINT8 *)(ImageHeader + 1);
+ } else {
+ //
+ // If the EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER is version 1, only match ImageTypeId.
+ // Header should exclude UpdateHardwareInstance field
+ //
+ Image = (UINT8 *)ImageHeader + ((EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *) 0)->UpdateHardwareInstance;
+ }
+
+ if (ImageHeader->UpdateVendorCodeSize == 0) {
+ Status = Fmp->SetImage(
+ Fmp,
+ TempFmpImageInfo->ImageIndex, // ImageIndex
+ Image, // Image
+ ImageHeader->UpdateImageSize, // ImageSize
+ NULL, // VendorCode
+ Update_Image_Progress, // Progress
+ &AbortReason // AbortReason
+ );
+ } else {
+ Status = Fmp->SetImage(
+ Fmp,
+ TempFmpImageInfo->ImageIndex, // ImageIndex
+ Image, // Image
+ ImageHeader->UpdateImageSize, // ImageSize
+ Image + ImageHeader->UpdateImageSize, // VendorCode
+ Update_Image_Progress, // Progress
+ &AbortReason // AbortReason
+ );
+ }
+ if (AbortReason != NULL) {
+ DEBUG ((EFI_D_ERROR, "%s\n", AbortReason));
+ FreePool(AbortReason);
+ }
+ //
+ // Update EsrtEntry For V1, V2 FMP instance. V3 FMP ESRT cache will be synced up through EsrtSyncFmp interface
+ //
+ if (FmpImageInfoDescriptorVer < EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION && EsrtProtocol != NULL) {
+ StatusEsrt = EsrtProtocol->GetEsrtEntry(&CapsuleHeader->CapsuleGuid, &EsrtEntry);
+ if (!EFI_ERROR(StatusEsrt)){
+ if (!EFI_ERROR(Status)) {
+ EsrtEntry.LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;
+ } else {
+ EsrtEntry.LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL;
+ }
+ EsrtEntry.LastAttemptVersion = 0;
+ EsrtProtocol->UpdateEsrtEntry(&EsrtEntry);
+ }
+ }
+ }
+ }
+ //
+ // Use DescriptorSize to move ImageInfo Pointer to stay compatible with different ImageInfo version
+ //
+ TempFmpImageInfo = (EFI_FIRMWARE_IMAGE_DESCRIPTOR *)((UINT8 *)TempFmpImageInfo + DescriptorSize);
+ }
+ FreePool(FmpImageInfoBuf);
+ }
+ }
+
+EXIT:
+
+ if (HandleBuffer != NULL) {
+ FreePool(HandleBuffer);
+ }
+
+ if (DriverDevicePath != NULL) {
+ FreePool(DriverDevicePath);
+ }
+
+ return Status;
+}
+
+
+/**
+ Those capsules supported by the firmwares.
+
+ @param CapsuleHeader Points to a capsule header.
+
+ @retval EFI_SUCESS Input capsule is supported by firmware.
+ @retval EFI_UNSUPPORTED Input capsule is not supported by the firmware.
+ @retval EFI_INVALID_PARAMETER Input capsule layout is not correct
+
+**/
+EFI_STATUS
+EFIAPI
+SupportCapsuleImage (
+ IN EFI_CAPSULE_HEADER *CapsuleHeader
+ )
+{
+ EFI_STATUS Status;
+ EFI_SYSTEM_RESOURCE_ENTRY EsrtEntry;
+ ESRT_MANAGEMENT_PROTOCOL *EsrtProtocol;
+
+ //
+ // We may need to add Hook point for OEM known Guids like gFwUpdateDisplayCapsuleGuid
+ //
+
+ //
+ // check Display Capsule Guid
+ //
+ if (CompareGuid(&gWindowsUxCapsuleGuid, &CapsuleHeader->CapsuleGuid)) {
+ return EFI_SUCCESS;
+ }
+
+ if (CompareGuid (&gEfiFmpCapsuleGuid, &CapsuleHeader->CapsuleGuid)) {
+ //
+ // Check layout of FMP capsule
+ //
+ return ValidateFmpCapsule(CapsuleHeader);
+ }
+
+ Status = gBS->LocateProtocol(&gEsrtManagementProtocolGuid, NULL, (VOID **)&EsrtProtocol);
+ if (EFI_ERROR(Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Status = EsrtProtocol->GetEsrtEntry(&CapsuleHeader->CapsuleGuid, &EsrtEntry);
+ if (!EFI_ERROR(Status)) {
+ return EFI_SUCCESS;
+ }
+
+ return EFI_UNSUPPORTED;
+}
+
+
+/**
+ The firmware implements to process the capsule image.
+
+ @param CapsuleHeader Points to a capsule header.
+
+ @retval EFI_SUCESS Process Capsule Image successfully.
+ @retval EFI_UNSUPPORTED Capsule image is not supported by the firmware.
+ @retval EFI_VOLUME_CORRUPTED FV volume in the capsule is corrupted.
+ @retval EFI_OUT_OF_RESOURCES Not enough memory.
+**/
+EFI_STATUS
+EFIAPI
+ProcessCapsuleImage (
+ IN EFI_CAPSULE_HEADER *CapsuleHeader
+ )
+{
+ UINT32 Length;
+ EFI_FIRMWARE_VOLUME_HEADER *FvImage;
+ EFI_FIRMWARE_VOLUME_HEADER *ProcessedFvImage;
+ EFI_STATUS Status;
+ EFI_STATUS StatusEsrt;
+ EFI_HANDLE FvProtocolHandle;
+ UINT32 FvAlignment;
+ EFI_SYSTEM_RESOURCE_ENTRY EsrtEntry;
+ UINT32 AttemptStatus;
+ ESRT_MANAGEMENT_PROTOCOL *EsrtManagement;
+
+ FvImage = NULL;
+ ProcessedFvImage = NULL;
+ Status = EFI_SUCCESS;
+ AttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;
+ DEBUG ((DEBUG_INFO, "ProcessCapsuleImage1\n"));
+
+ if (SupportCapsuleImage (CapsuleHeader) != EFI_SUCCESS) {
+ return EFI_UNSUPPORTED;
+ }
+ DEBUG ((DEBUG_INFO, "ProcessCapsuleImage2\n"));
+
+ //
+ // Display image in firmware update display capsule
+ //
+ if (CompareGuid(&gWindowsUxCapsuleGuid, &CapsuleHeader->CapsuleGuid)) {
+ return DisplayCapsuleImage(
+ (DISPLAY_DISPLAY_PAYLOAD *)(CapsuleHeader + 1),
+ (UINTN)(CapsuleHeader->CapsuleImageSize - sizeof(EFI_CAPSULE_HEADER)));
+ }
+ DEBUG ((DEBUG_INFO, "ProcessCapsuleImage3\n"));
+
+ //
+ // Check FMP capsule layout
+ //
+ if (CompareGuid (&gEfiFmpCapsuleGuid, &CapsuleHeader->CapsuleGuid)){
+ Status = ValidateFmpCapsule(CapsuleHeader);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+ DEBUG ((DEBUG_INFO, "ProcessCapsuleImage4\n"));
+
+ //
+ // Press EFI FMP Capsule
+ //
+ Status = ProcessFmpCapsuleImage(CapsuleHeader);
+ DEBUG ((DEBUG_INFO, "ProcessCapsuleImage5\n"));
+
+ //
+ // Indicate to sync Esrt on next boot
+ //
+ PcdSetBool(PcdEsrtSyncFmp, TRUE);
+ DEBUG ((DEBUG_INFO, "ProcessCapsuleImage6\n"));
+
+ return Status;
+ }
+ DEBUG ((DEBUG_INFO, "ProcessCapsuleImage7\n"));
+
+ //
+ // Other non-FMP capsule handler
+ //
+ // Skip the capsule header, move to the Firware Volume
+ //
+ FvImage = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINT8 *) CapsuleHeader + CapsuleHeader->HeaderSize);
+ Length = CapsuleHeader->CapsuleImageSize - CapsuleHeader->HeaderSize;
+
+ while (Length != 0) {
+ //
+ // Point to the next firmware volume header, and then
+ // call the DXE service to process it.
+ //
+ DEBUG ((DEBUG_INFO, "ProcessCapsuleImage8\n"));
+ if (FvImage->FvLength > (UINTN) Length) {
+ //
+ // Notes: need to stuff this status somewhere so that the
+ // error can be detected at OS runtime
+ //
+ Status = EFI_VOLUME_CORRUPTED;
+ break;
+ }
+ DEBUG ((DEBUG_INFO, "ProcessCapsuleImage9\n"));
+
+ FvAlignment = 1 << ((FvImage->Attributes & EFI_FVB2_ALIGNMENT) >> 16);
+ //
+ // FvAlignment must be more than 8 bytes required by FvHeader structure.
+ //
+ if (FvAlignment < 8) {
+ FvAlignment = 8;
+ }
+ DEBUG ((DEBUG_INFO, "ProcessCapsuleImage10\n"));
+ //
+ // Check FvImage Align is required.
+ //
+ if (((UINTN) FvImage % FvAlignment) == 0) {
+ ProcessedFvImage = FvImage;
+ } else {
+ //
+ // Allocate new aligned buffer to store FvImage.
+ //
+ ProcessedFvImage = (EFI_FIRMWARE_VOLUME_HEADER *) AllocateAlignedPages ((UINTN) EFI_SIZE_TO_PAGES ((UINTN) FvImage->FvLength), (UINTN) FvAlignment);
+ if (ProcessedFvImage == NULL) {
+ AttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INSUFFICIENT_RESOURCES;
+ Status = EFI_OUT_OF_RESOURCES;
+ break;
+ }
+ CopyMem (ProcessedFvImage, FvImage, (UINTN) FvImage->FvLength);
+ }
+ DEBUG ((DEBUG_INFO, "ProcessCapsuleImage11\n"));
+
+ Status = gDS->ProcessFirmwareVolume (
+ (VOID *) ProcessedFvImage,
+ (UINTN) ProcessedFvImage->FvLength,
+ &FvProtocolHandle
+ );
+ if (EFI_ERROR (Status)) {
+ AttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INVALID_FORMAT;
+ break;
+ }
+ DEBUG ((DEBUG_INFO, "ProcessCapsuleImage12\n"));
+
+ //
+ // Call the dispatcher to dispatch any drivers from the produced firmware volume
+ //
+ gDS->Dispatch ();
+ DEBUG ((DEBUG_INFO, "ProcessCapsuleImage13\n"));
+ //
+ // On to the next FV in the capsule
+ //
+ Length -= (UINT32) FvImage->FvLength;
+ FvImage = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINT8 *) FvImage + FvImage->FvLength);
+ }
+
+ //
+ // Update corresponding ESRT entry LastAttemp Status
+ //
+ StatusEsrt = gBS->LocateProtocol(&gEsrtManagementProtocolGuid, NULL, (VOID **)&EsrtManagement);
+ DEBUG ((DEBUG_INFO, "ProcessCapsuleImage14\n"));
+ if (!EFI_ERROR(StatusEsrt)) {
+ StatusEsrt = EsrtManagement->GetEsrtEntry(&CapsuleHeader->CapsuleGuid, &EsrtEntry);
+ DEBUG ((DEBUG_INFO, "ProcessCapsuleImage15\n"));
+ if (!EFI_ERROR(StatusEsrt)){
+ //
+ // Update version can't be get from FV, set LastAttemptVersion to zero after a failed update
+ //
+ if (AttemptStatus != LAST_ATTEMPT_STATUS_SUCCESS) {
+ EsrtEntry.LastAttemptVersion = 0;
+ }
+ DEBUG ((DEBUG_INFO, "ProcessCapsuleImage16\n"));
+ EsrtEntry.LastAttemptStatus = AttemptStatus;
+ EsrtManagement->UpdateEsrtEntry(&EsrtEntry);
+ DEBUG ((DEBUG_INFO, "ProcessCapsuleImage17\n"));
+ }
+ }
+
+ //
+ // Indicate to sync Esrt on next boot
+ //
+ PcdSetBool(PcdEsrtSyncFmp, TRUE);
+ DEBUG ((DEBUG_INFO, "ProcessCapsuleImage18\n"));
+
+ return Status;
+}
+
+
+/**
+ The constructor function of DxeCapsuleLib.
+
+ @param ImageHandle The firmware allocated handle for the EFI image.
+ @param SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The constructor successfully .
+ @retval Other value The constructor can't add string package.
+
+**/
+EFI_STATUS
+EFIAPI
+DxeCapsuleLibConstructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ return EFI_SUCCESS;
+}
diff --git a/Vlv2TbltDevicePkg/Library/DxeEsrtCapsuleBsLib/DxeEsrtCapsuleBsLib.inf b/Vlv2TbltDevicePkg/Library/DxeEsrtCapsuleBsLib/DxeEsrtCapsuleBsLib.inf
new file mode 100644
index 0000000000..7441faa3f4
--- /dev/null
+++ b/Vlv2TbltDevicePkg/Library/DxeEsrtCapsuleBsLib/DxeEsrtCapsuleBsLib.inf
@@ -0,0 +1,62 @@
+## @file
+# Component description file for Capsule Boottime Library
+#
+#
+# Copyright (c) 2004 - 2016, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php.
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = DxeCapsuleLib
+ FILE_GUID = 534E35DE-8EB3-47b3-A4E0-72A571E50733
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = CapsuleLib|DXE_DRIVER UEFI_APPLICATION
+ CONSTRUCTOR = DxeCapsuleLibConstructor
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources]
+ DxeCapsuleLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ #BpCommonPkg/BpCommonPkg.dec
+ IntelFrameworkPkg/IntelFrameworkPkg.dec
+ Vlv2TbltDevicePkg/PlatformPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ MemoryAllocationLib
+ DxeServicesTableLib
+ UefiBootServicesTableLib
+ UefiBootManagerLib
+ DevicePathLib
+
+[Pcd]
+ gPlatformModuleTokenSpaceGuid.PcdEsrtSyncFmp
+
+[Protocols]
+ gEsrtManagementProtocolGuid ## CONSUMES
+ gEfiFirmwareManagementProtocolGuid ## SOMETIMES_CONSUMES
+
+[Guids]
+ gEfiCapsuleGuid ## SOMETIMES_CONSUMED ## GUID
+ gEfiFmpCapsuleGuid ## SOMETIMES_CONSUMES ## GUID
+ gWindowsUxCapsuleGuid ## SOMETIMES_CONSUMES ## GUID
diff --git a/Vlv2TbltDevicePkg/Library/DxeEsrtCapsuleRtLib/DxeCapsuleLib.c b/Vlv2TbltDevicePkg/Library/DxeEsrtCapsuleRtLib/DxeCapsuleLib.c
new file mode 100644
index 0000000000..604cb3db02
--- /dev/null
+++ b/Vlv2TbltDevicePkg/Library/DxeEsrtCapsuleRtLib/DxeCapsuleLib.c
@@ -0,0 +1,1038 @@
+/** @file
+ Capsule Runtime Library instance to update capsule image to flash.
+
+ Copyright (c) 2004 - 2016, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+
+#include <PiDxe.h>
+
+#include <IndustryStandard/Bmp.h>
+#include <IndustryStandard/WindowsUxCapsule.h>
+
+#include <Guid/FmpCapsule.h>
+#include <Guid/Capsule.h>
+#include <Guid/SystemResourceTable.h>
+#include <Guid/EventGroup.h>
+
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/CapsuleLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/UefiBootManagerLib.h>
+
+#include <Protocol/GraphicsOutput.h>
+#include <Protocol/EsrtManagement.h>
+#include <Protocol/FirmwareManagement.h>
+#include <Protocol/DevicePath.h>
+
+EFI_SYSTEM_RESOURCE_TABLE *mEsrtTable = NULL;
+BOOLEAN mIsVirtualAddrConverted = FALSE;
+
+
+/**
+ Function indicate the current completion progress of the firmware
+ update. Platform may override with own specific progress function.
+
+ @param Completion A value between 1 and 100 indicating the current completion progress of the firmware update
+
+ @retval EFI_SUCESS Input capsule is a correct FMP capsule.
+**/
+EFI_STATUS
+EFIAPI
+Update_Image_Progress (
+ IN UINTN Completion
+)
+{
+ return EFI_SUCCESS;
+}
+
+/**
+ Validate Fmp capsules layout.
+
+ @param CapsuleHeader Points to a capsule header.
+
+ @retval EFI_SUCESS Input capsule is a correct FMP capsule.
+ @retval EFI_INVALID_PARAMETER Input capsule is not a correct FMP capsule.
+**/
+EFI_STATUS
+ValidateFmpCapsule (
+ IN EFI_CAPSULE_HEADER *CapsuleHeader
+ )
+{
+ EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *FmpCapsuleHeader;
+ UINT8 *EndOfCapsule;
+ EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader;
+ UINT8 *EndOfPayload;
+ UINT64 *ItemOffsetList;
+ UINT32 ItemNum;
+ UINTN Index;
+
+ FmpCapsuleHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *) ((UINT8 *) CapsuleHeader + CapsuleHeader->HeaderSize);
+ EndOfCapsule = (UINT8 *) CapsuleHeader + CapsuleHeader->CapsuleImageSize;
+
+ if (FmpCapsuleHeader->Version > EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION) {
+ return EFI_INVALID_PARAMETER;
+ }
+ ItemOffsetList = (UINT64 *)(FmpCapsuleHeader + 1);
+
+ ItemNum = FmpCapsuleHeader->EmbeddedDriverCount + FmpCapsuleHeader->PayloadItemCount;
+
+ if (ItemNum == FmpCapsuleHeader->EmbeddedDriverCount) {
+ //
+ // No payload element
+ //
+ if (((UINT8 *)FmpCapsuleHeader + ItemOffsetList[ItemNum - 1]) < EndOfCapsule) {
+ return EFI_SUCCESS;
+ } else {
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ if (FmpCapsuleHeader->PayloadItemCount != 0) {
+ //
+ // Check if the last payload is within capsule image range
+ //
+ ImageHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *)((UINT8 *)FmpCapsuleHeader + ItemOffsetList[ItemNum - 1]);
+ EndOfPayload = (UINT8 *)(ImageHeader + 1) + ImageHeader->UpdateImageSize + ImageHeader->UpdateVendorCodeSize;
+ } else {
+ //
+ // No driver & payload element in FMP
+ //
+ EndOfPayload = (UINT8 *)(FmpCapsuleHeader + 1);
+ }
+
+ if (EndOfPayload != EndOfCapsule) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // All the address in ItemOffsetList must be stored in ascending order
+ //
+ if (ItemNum >= 2) {
+ for (Index = 0; Index < ItemNum - 1; Index++) {
+ if (ItemOffsetList[Index] >= ItemOffsetList[Index + 1]) {
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Convert a *.BMP graphics image to a GOP blt buffer. If a NULL Blt buffer
+ is passed in a GopBlt buffer will be allocated by this routine. If a GopBlt
+ buffer is passed in it will be used if it is big enough.
+
+ @param BmpImage Pointer to BMP file
+ @param BmpImageSize Number of bytes in BmpImage
+ @param GopBlt Buffer containing GOP version of BmpImage.
+ @param GopBltSize Size of GopBlt in bytes.
+ @param PixelHeight Height of GopBlt/BmpImage in pixels
+ @param PixelWidth Width of GopBlt/BmpImage in pixels
+
+ @retval EFI_SUCCESS GopBlt and GopBltSize are returned.
+ @retval EFI_UNSUPPORTED BmpImage is not a valid *.BMP image
+ @retval EFI_BUFFER_TOO_SMALL The passed in GopBlt buffer is not big enough.
+ GopBltSize will contain the required size.
+ @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate.
+
+**/
+static
+EFI_STATUS
+ConvertBmpToGopBlt (
+ IN VOID *BmpImage,
+ IN UINTN BmpImageSize,
+ IN OUT VOID **GopBlt,
+ IN OUT UINTN *GopBltSize,
+ OUT UINTN *PixelHeight,
+ OUT UINTN *PixelWidth
+ )
+{
+ UINT8 *Image;
+ UINT8 *ImageHeader;
+ BMP_IMAGE_HEADER *BmpHeader;
+ BMP_COLOR_MAP *BmpColorMap;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;
+ UINT64 BltBufferSize;
+ UINTN Index;
+ UINTN Height;
+ UINTN Width;
+ UINTN ImageIndex;
+ BOOLEAN IsAllocated;
+
+ BmpHeader = (BMP_IMAGE_HEADER *) BmpImage;
+
+ if (BmpHeader->CharB != 'B' || BmpHeader->CharM != 'M') {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Doesn't support compress.
+ //
+ if (BmpHeader->CompressionType != 0) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Calculate Color Map offset in the image.
+ //
+ Image = BmpImage;
+ BmpColorMap = (BMP_COLOR_MAP *) (Image + sizeof (BMP_IMAGE_HEADER));
+
+ //
+ // Calculate graphics image data address in the image
+ //
+ Image = ((UINT8 *) BmpImage) + BmpHeader->ImageOffset;
+ ImageHeader = Image;
+
+ //
+ // Calculate the BltBuffer needed size.
+ //
+ BltBufferSize = MultU64x32 ((UINT64) BmpHeader->PixelWidth, BmpHeader->PixelHeight);
+ //
+ // Ensure the BltBufferSize * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) doesn't overflow
+ //
+ if (BltBufferSize > DivU64x32 ((UINTN) ~0, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL))) {
+ return EFI_UNSUPPORTED;
+ }
+ BltBufferSize = MultU64x32 (BltBufferSize, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
+
+ IsAllocated = FALSE;
+ if (*GopBlt == NULL) {
+ //
+ // GopBlt is not allocated by caller.
+ //
+ *GopBltSize = (UINTN) BltBufferSize;
+ *GopBlt = AllocatePool (*GopBltSize);
+ IsAllocated = TRUE;
+ if (*GopBlt == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ } else {
+ //
+ // GopBlt has been allocated by caller.
+ //
+ if (*GopBltSize < (UINTN) BltBufferSize) {
+ *GopBltSize = (UINTN) BltBufferSize;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+ }
+
+ *PixelWidth = BmpHeader->PixelWidth;
+ *PixelHeight = BmpHeader->PixelHeight;
+
+ //
+ // Convert image from BMP to Blt buffer format
+ //
+ BltBuffer = *GopBlt;
+ for (Height = 0; Height < BmpHeader->PixelHeight; Height++) {
+ Blt = &BltBuffer[(BmpHeader->PixelHeight - Height - 1) * BmpHeader->PixelWidth];
+ for (Width = 0; Width < BmpHeader->PixelWidth; Width++, Image++, Blt++) {
+ switch (BmpHeader->BitPerPixel) {
+ case 1:
+ //
+ // Convert 1-bit (2 colors) BMP to 24-bit color
+ //
+ for (Index = 0; Index < 8 && Width < BmpHeader->PixelWidth; Index++) {
+ Blt->Red = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Red;
+ Blt->Green = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Green;
+ Blt->Blue = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Blue;
+ Blt++;
+ Width++;
+ }
+
+ Blt--;
+ Width--;
+ break;
+
+ case 4:
+ //
+ // Convert 4-bit (16 colors) BMP Palette to 24-bit color
+ //
+ Index = (*Image) >> 4;
+ Blt->Red = BmpColorMap[Index].Red;
+ Blt->Green = BmpColorMap[Index].Green;
+ Blt->Blue = BmpColorMap[Index].Blue;
+ if (Width < (BmpHeader->PixelWidth - 1)) {
+ Blt++;
+ Width++;
+ Index = (*Image) & 0x0f;
+ Blt->Red = BmpColorMap[Index].Red;
+ Blt->Green = BmpColorMap[Index].Green;
+ Blt->Blue = BmpColorMap[Index].Blue;
+ }
+ break;
+
+ case 8:
+ //
+ // Convert 8-bit (256 colors) BMP Palette to 24-bit color
+ //
+ Blt->Red = BmpColorMap[*Image].Red;
+ Blt->Green = BmpColorMap[*Image].Green;
+ Blt->Blue = BmpColorMap[*Image].Blue;
+ break;
+
+ case 24:
+ //
+ // It is 24-bit BMP.
+ //
+ Blt->Blue = *Image++;
+ Blt->Green = *Image++;
+ Blt->Red = *Image;
+ break;
+
+ case 32:
+ //
+ // it is 32-bit BMP. Skip pixel's highest byte
+ //
+ Blt->Blue = *Image++;
+ Blt->Green = *Image++;
+ Blt->Red = *Image++;
+ break;
+
+ default:
+ //
+ // Other bit format BMP is not supported.
+ //
+ if (IsAllocated) {
+ FreePool (*GopBlt);
+ *GopBlt = NULL;
+ }
+ return EFI_UNSUPPORTED;
+ break;
+ };
+
+ }
+
+ ImageIndex = (UINTN) (Image - ImageHeader);
+ if ((ImageIndex % 4) != 0) {
+ //
+ // Bmp Image starts each row on a 32-bit boundary!
+ //
+ Image = Image + (4 - (ImageIndex % 4));
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Those capsules supported by the firmwares.
+
+ @param CapsuleHeader Points to a capsule header.
+
+ @retval EFI_SUCESS Input capsule is supported by firmware.
+ @retval EFI_UNSUPPORTED Input capsule is not supported by the firmware.
+**/
+EFI_STATUS
+DisplayCapsuleImage (
+ IN DISPLAY_DISPLAY_PAYLOAD *ImagePayload,
+ IN UINTN PayloadSize
+ )
+{
+ EFI_STATUS Status;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;
+ UINTN BltSize;
+ UINTN Height;
+ UINTN Width;
+ EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
+
+ //
+ // Only Support Bitmap by now
+ //
+ if (ImagePayload->ImageType != 0) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Try to open GOP
+ //
+ Status = gBS->HandleProtocol (gST->ConsoleOutHandle, &gEfiGraphicsOutputProtocolGuid, (VOID **)&GraphicsOutput);
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ if (GraphicsOutput->Mode->Mode != ImagePayload->Mode) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Blt = NULL;
+ Width = 0;
+ Height = 0;
+ Status = ConvertBmpToGopBlt (
+ ImagePayload + 1,
+ PayloadSize - sizeof(DISPLAY_DISPLAY_PAYLOAD),
+ (VOID **)&Blt,
+ &BltSize,
+ &Height,
+ &Width
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = GraphicsOutput->Blt (
+ GraphicsOutput,
+ Blt,
+ EfiBltBufferToVideo,
+ 0,
+ 0,
+ (UINTN) ImagePayload->OffsetX,
+ (UINTN) ImagePayload->OffsetY,
+ Width,
+ Height,
+ Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
+ );
+
+ FreePool(Blt);
+
+ return Status;
+}
+
+/**
+ Process Firmware management protocol data capsule.
+
+ @param CapsuleHeader Points to a capsule header.
+
+ @retval EFI_SUCESS Process Capsule Image successfully.
+ @retval EFI_UNSUPPORTED Capsule image is not supported by the firmware.
+ @retval EFI_VOLUME_CORRUPTED FV volume in the capsule is corrupted.
+ @retval EFI_OUT_OF_RESOURCES Not enough memory.
+**/
+EFI_STATUS
+ProcessFmpCapsuleImage (
+ IN EFI_CAPSULE_HEADER *CapsuleHeader
+ )
+{
+ EFI_STATUS Status;
+ EFI_STATUS StatusEsrt;
+ EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *FmpCapsuleHeader;
+ UINT8 *EndOfCapsule;
+ EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader;
+ UINT8 *Image;
+ EFI_HANDLE ImageHandle;
+ UINT64 *ItemOffsetList;
+ UINT32 ItemNum;
+ UINTN Index;
+ UINTN ExitDataSize;
+ EFI_HANDLE *HandleBuffer;
+ EFI_FIRMWARE_MANAGEMENT_PROTOCOL *Fmp;
+ UINTN NumberOfHandles;
+ UINTN DescriptorSize;
+ UINT8 FmpImageInfoCount;
+ UINT32 FmpImageInfoDescriptorVer;
+ UINTN ImageInfoSize;
+ UINT32 PackageVersion;
+ CHAR16 *PackageVersionName;
+ CHAR16 *AbortReason;
+ EFI_FIRMWARE_IMAGE_DESCRIPTOR *FmpImageInfoBuf;
+ EFI_FIRMWARE_IMAGE_DESCRIPTOR *TempFmpImageInfo;
+ UINTN DriverLen;
+ UINTN Index1;
+ UINTN Index2;
+ MEMMAP_DEVICE_PATH MemMapNode;
+ EFI_DEVICE_PATH_PROTOCOL *DriverDevicePath;
+ ESRT_MANAGEMENT_PROTOCOL *EsrtProtocol;
+ EFI_SYSTEM_RESOURCE_ENTRY EsrtEntry;
+
+ Status = EFI_SUCCESS;
+ HandleBuffer = NULL;
+ ExitDataSize = 0;
+ DriverDevicePath = NULL;
+ EsrtProtocol = NULL;
+
+ FmpCapsuleHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *) ((UINT8 *) CapsuleHeader + CapsuleHeader->HeaderSize);
+ EndOfCapsule = (UINT8 *) CapsuleHeader + CapsuleHeader->CapsuleImageSize;
+
+ if (FmpCapsuleHeader->Version > EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION) {
+ return EFI_INVALID_PARAMETER;
+ }
+ ItemOffsetList = (UINT64 *)(FmpCapsuleHeader + 1);
+
+ ItemNum = FmpCapsuleHeader->EmbeddedDriverCount + FmpCapsuleHeader->PayloadItemCount;
+
+ //
+ // capsule in which driver count and payload count are both zero is not processed.
+ //
+ if (ItemNum == 0) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Update corresponding ESRT entry LastAttemp Status
+ //
+ Status = gBS->LocateProtocol(&gEsrtManagementProtocolGuid, NULL, (VOID **)&EsrtProtocol);
+
+ //
+ // 1. ConnectAll to ensure
+ // All the communication protocol required by driver in capsule installed
+ // All FMP protocols are installed
+ //
+ EfiBootManagerConnectAll();
+
+
+ //
+ // 2. Try to load & start all the drivers within capsule
+ //
+ SetDevicePathNodeLength (&MemMapNode.Header, sizeof (MemMapNode));
+ MemMapNode.Header.Type = HARDWARE_DEVICE_PATH;
+ MemMapNode.Header.SubType = HW_MEMMAP_DP;
+ MemMapNode.MemoryType = EfiBootServicesCode;
+ MemMapNode.StartingAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)CapsuleHeader;
+ MemMapNode.EndingAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)((UINT8 *)CapsuleHeader + CapsuleHeader->CapsuleImageSize - 1);
+
+ DriverDevicePath = AppendDevicePathNode (NULL, &MemMapNode.Header);
+ if (DriverDevicePath == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ for (Index = 0; Index < FmpCapsuleHeader->EmbeddedDriverCount; Index++) {
+ if (FmpCapsuleHeader->PayloadItemCount == 0 && Index == (UINTN)FmpCapsuleHeader->EmbeddedDriverCount - 1) {
+ //
+ // When driver is last element in the ItemOffsetList array, the driver size is calculated by reference CapsuleImageSize in EFI_CAPSULE_HEADER
+ //
+ DriverLen = CapsuleHeader->CapsuleImageSize - CapsuleHeader->HeaderSize - (UINTN)ItemOffsetList[Index];
+ } else {
+ DriverLen = (UINTN)ItemOffsetList[Index + 1] - (UINTN)ItemOffsetList[Index];
+ }
+
+ Status = gBS->LoadImage(
+ FALSE,
+ gImageHandle,
+ DriverDevicePath,
+ (UINT8 *)FmpCapsuleHeader + ItemOffsetList[Index],
+ DriverLen,
+ &ImageHandle
+ );
+ if (EFI_ERROR(Status)) {
+ goto EXIT;
+ }
+
+ Status = gBS->StartImage(
+ ImageHandle,
+ &ExitDataSize,
+ NULL
+ );
+ if (EFI_ERROR(Status)) {
+ DEBUG ((DEBUG_ERROR, "Driver Return Status = %r\n", Status));
+ goto EXIT;
+ }
+ }
+
+ //
+ // Connnect all again to connect drivers within capsule
+ //
+ if (FmpCapsuleHeader->EmbeddedDriverCount > 0) {
+ EfiBootManagerConnectAll();
+ }
+
+ //
+ // 3. Route payload to right FMP instance
+ //
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiFirmwareManagementProtocolGuid,
+ NULL,
+ &NumberOfHandles,
+ &HandleBuffer
+ );
+
+ if (!EFI_ERROR(Status)) {
+ for(Index1 = 0; Index1 < NumberOfHandles; Index1++) {
+ Status = gBS->HandleProtocol(
+ HandleBuffer[Index1],
+ &gEfiFirmwareManagementProtocolGuid,
+ (VOID **)&Fmp
+ );
+ if (EFI_ERROR(Status)) {
+ continue;
+ }
+
+ ImageInfoSize = 0;
+ Status = Fmp->GetImageInfo (
+ Fmp,
+ &ImageInfoSize,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ );
+ if (Status != EFI_BUFFER_TOO_SMALL) {
+ continue;
+ }
+
+ FmpImageInfoBuf = NULL;
+ FmpImageInfoBuf = AllocateZeroPool (ImageInfoSize);
+ if (FmpImageInfoBuf == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto EXIT;
+ }
+
+ PackageVersionName = NULL;
+ Status = Fmp->GetImageInfo (
+ Fmp,
+ &ImageInfoSize, // ImageInfoSize
+ FmpImageInfoBuf, // ImageInfo
+ &FmpImageInfoDescriptorVer, // DescriptorVersion
+ &FmpImageInfoCount, // DescriptorCount
+ &DescriptorSize, // DescriptorSize
+ &PackageVersion, // PackageVersion
+ &PackageVersionName // PackageVersionName
+ );
+
+ //
+ // If FMP GetInformation interface failed, skip this resource
+ //
+ if (EFI_ERROR(Status)) {
+ FreePool(FmpImageInfoBuf);
+ continue;
+ }
+
+ if (PackageVersionName != NULL) {
+ FreePool(PackageVersionName);
+ }
+
+ TempFmpImageInfo = FmpImageInfoBuf;
+ for (Index2 = 0; Index2 < FmpImageInfoCount; Index2++) {
+ //
+ // Check all the payload entry in capsule payload list
+ //
+ for (Index = FmpCapsuleHeader->EmbeddedDriverCount; Index < ItemNum; Index++) {
+ ImageHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *)((UINT8 *)FmpCapsuleHeader + ItemOffsetList[Index]);
+ if (CompareGuid(&ImageHeader->UpdateImageTypeId, &TempFmpImageInfo->ImageTypeId) &&
+ ImageHeader->UpdateImageIndex == TempFmpImageInfo->ImageIndex) {
+ AbortReason = NULL;
+ if (ImageHeader->Version >= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {
+ if(ImageHeader->UpdateHardwareInstance != 0){
+ //
+ // FMP Version is >=2 & UpdateHardwareInstance Skip 2 case
+ // 1. FMP Image info Version < 3
+ // 2. HardwareInstance doesn't match
+ //
+ if (FmpImageInfoDescriptorVer < EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION ||
+ ImageHeader->UpdateHardwareInstance != TempFmpImageInfo->HardwareInstance) {
+ continue;
+ }
+ }
+ Image = (UINT8 *)(ImageHeader + 1);
+ } else {
+ //
+ // If the EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER is version 1, only match ImageTypeId.
+ // Header should exclude UpdateHardwareInstance field
+ //
+ Image = (UINT8 *)ImageHeader + ((EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *) 0)->UpdateHardwareInstance;
+ }
+
+ if (ImageHeader->UpdateVendorCodeSize == 0) {
+ Status = Fmp->SetImage(
+ Fmp,
+ TempFmpImageInfo->ImageIndex, // ImageIndex
+ Image, // Image
+ ImageHeader->UpdateImageSize, // ImageSize
+ NULL, // VendorCode
+ Update_Image_Progress, // Progress
+ &AbortReason // AbortReason
+ );
+ } else {
+ Status = Fmp->SetImage(
+ Fmp,
+ TempFmpImageInfo->ImageIndex, // ImageIndex
+ Image, // Image
+ ImageHeader->UpdateImageSize, // ImageSize
+ Image + ImageHeader->UpdateImageSize, // VendorCode
+ Update_Image_Progress, // Progress
+ &AbortReason // AbortReason
+ );
+ }
+ if (AbortReason != NULL) {
+ DEBUG ((EFI_D_ERROR, "%s\n", AbortReason));
+ FreePool(AbortReason);
+ }
+ //
+ // Update EsrtEntry For V1, V2 FMP instance. V3 FMP ESRT cache will be synced up through EsrtSyncFmp interface
+ //
+ if (FmpImageInfoDescriptorVer < EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION && EsrtProtocol != NULL) {
+ StatusEsrt = EsrtProtocol->GetEsrtEntry(&CapsuleHeader->CapsuleGuid, &EsrtEntry);
+ if (!EFI_ERROR(StatusEsrt)){
+ if (!EFI_ERROR(Status)) {
+ EsrtEntry.LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;
+ } else {
+ EsrtEntry.LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL;
+ }
+ EsrtEntry.LastAttemptVersion = 0;
+ EsrtProtocol->UpdateEsrtEntry(&EsrtEntry);
+ }
+ }
+ }
+ }
+ //
+ // Use DescriptorSize to move ImageInfo Pointer to stay compatible with different ImageInfo version
+ //
+ TempFmpImageInfo = (EFI_FIRMWARE_IMAGE_DESCRIPTOR *)((UINT8 *)TempFmpImageInfo + DescriptorSize);
+ }
+ FreePool(FmpImageInfoBuf);
+ }
+ }
+
+EXIT:
+
+ if (HandleBuffer != NULL) {
+ FreePool(HandleBuffer);
+ }
+
+ if (DriverDevicePath != NULL) {
+ FreePool(DriverDevicePath);
+ }
+
+ return Status;
+}
+
+
+/**
+ Those capsules supported by the firmwares.
+
+ @param CapsuleHeader Points to a capsule header.
+
+ @retval EFI_SUCESS Input capsule is supported by firmware.
+ @retval EFI_UNSUPPORTED Input capsule is not supported by the firmware.
+ @retval EFI_INVALID_PARAMETER Input capsule layout is not correct
+
+**/
+EFI_STATUS
+EFIAPI
+SupportCapsuleImage (
+ IN EFI_CAPSULE_HEADER *CapsuleHeader
+ )
+{
+ EFI_STATUS Status;
+ EFI_SYSTEM_RESOURCE_ENTRY EsrtEntry;
+ EFI_SYSTEM_RESOURCE_ENTRY *EsrtArray;
+ ESRT_MANAGEMENT_PROTOCOL *EsrtProtocol;
+ UINTN i;
+
+ //
+ // We may need to add Hook point for OEM known Guids like gFwUpdateDisplayCapsuleGuid
+ //
+
+ //
+ // check Display Capsule Guid
+ //
+ if (CompareGuid(&gWindowsUxCapsuleGuid, &CapsuleHeader->CapsuleGuid)) {
+ return EFI_SUCCESS;
+ }
+
+ if (CompareGuid (&gEfiFmpCapsuleGuid, &CapsuleHeader->CapsuleGuid)) {
+ //
+ // Check layout of FMP capsule
+ //
+ return ValidateFmpCapsule(CapsuleHeader);
+ }
+
+ //
+ // Runtime directly check EsrtTable by virtual address
+ //
+ if (mIsVirtualAddrConverted) {
+ if(mEsrtTable == NULL) {
+ //
+ // Esrt table not found
+ //
+ return EFI_UNSUPPORTED;
+ }
+
+ EsrtArray = (EFI_SYSTEM_RESOURCE_ENTRY *)(mEsrtTable + 1);
+ for (i = 0 ; i < mEsrtTable->FwResourceCount ; i++){
+ if (CompareGuid(&(EsrtArray[i].FwClass), &CapsuleHeader->CapsuleGuid)){
+ return EFI_SUCCESS;
+ }
+ }
+
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Boot Time check
+ // Before ReadytoBoot Event
+ //
+ Status = gBS->LocateProtocol(&gEsrtManagementProtocolGuid, NULL, (VOID **)&EsrtProtocol);
+ if (EFI_ERROR(Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Status = EsrtProtocol->GetEsrtEntry(&CapsuleHeader->CapsuleGuid, &EsrtEntry);
+ if (!EFI_ERROR(Status)) {
+ return EFI_SUCCESS;
+ }
+
+ return EFI_UNSUPPORTED;
+}
+
+
+/**
+ The firmware implements to process the capsule image.
+
+ @param CapsuleHeader Points to a capsule header.
+
+ @retval EFI_SUCESS Process Capsule Image successfully.
+ @retval EFI_UNSUPPORTED Capsule image is not supported by the firmware.
+ @retval EFI_VOLUME_CORRUPTED FV volume in the capsule is corrupted.
+ @retval EFI_OUT_OF_RESOURCES Not enough memory.
+**/
+EFI_STATUS
+EFIAPI
+ProcessCapsuleImage (
+ IN EFI_CAPSULE_HEADER *CapsuleHeader
+ )
+{
+ UINT32 Length;
+ EFI_FIRMWARE_VOLUME_HEADER *FvImage;
+ EFI_FIRMWARE_VOLUME_HEADER *ProcessedFvImage;
+ EFI_STATUS Status;
+ EFI_STATUS StatusEsrt;
+ EFI_HANDLE FvProtocolHandle;
+ UINT32 FvAlignment;
+ EFI_SYSTEM_RESOURCE_ENTRY EsrtEntry;
+ UINT32 AttemptStatus;
+ ESRT_MANAGEMENT_PROTOCOL *EsrtManagement;
+
+ FvImage = NULL;
+ ProcessedFvImage = NULL;
+ Status = EFI_SUCCESS;
+ AttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;
+
+ if (SupportCapsuleImage (CapsuleHeader) != EFI_SUCCESS) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Display image in firmware update display capsule
+ //
+ if (CompareGuid(&gWindowsUxCapsuleGuid, &CapsuleHeader->CapsuleGuid)) {
+ return DisplayCapsuleImage(
+ (DISPLAY_DISPLAY_PAYLOAD *)(CapsuleHeader + 1),
+ (UINTN)(CapsuleHeader->CapsuleImageSize - sizeof(EFI_CAPSULE_HEADER)));
+ }
+
+ //
+ // Check FMP capsule layout
+ //
+ if (CompareGuid (&gEfiFmpCapsuleGuid, &CapsuleHeader->CapsuleGuid)){
+ Status = ValidateFmpCapsule(CapsuleHeader);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ //
+ // Press EFI FMP Capsule
+ //
+ Status = ProcessFmpCapsuleImage(CapsuleHeader);
+ //
+ // Indicate to sync Esrt on next boot
+ //
+ PcdSetBool(PcdEsrtSyncFmp, TRUE);
+
+ return Status;
+ }
+
+ //
+ // Other non-FMP capsule handler
+ //
+ // Skip the capsule header, move to the Firware Volume
+ //
+ FvImage = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINT8 *) CapsuleHeader + CapsuleHeader->HeaderSize);
+ Length = CapsuleHeader->CapsuleImageSize - CapsuleHeader->HeaderSize;
+
+ while (Length != 0) {
+ //
+ // Point to the next firmware volume header, and then
+ // call the DXE service to process it.
+ //
+ if (FvImage->FvLength > (UINTN) Length) {
+ //
+ // Notes: need to stuff this status somewhere so that the
+ // error can be detected at OS runtime
+ //
+ Status = EFI_VOLUME_CORRUPTED;
+ break;
+ }
+
+ FvAlignment = 1 << ((FvImage->Attributes & EFI_FVB2_ALIGNMENT) >> 16);
+ //
+ // FvAlignment must be more than 8 bytes required by FvHeader structure.
+ //
+ if (FvAlignment < 8) {
+ FvAlignment = 8;
+ }
+ //
+ // Check FvImage Align is required.
+ //
+ if (((UINTN) FvImage % FvAlignment) == 0) {
+ ProcessedFvImage = FvImage;
+ } else {
+ //
+ // Allocate new aligned buffer to store FvImage.
+ //
+ ProcessedFvImage = (EFI_FIRMWARE_VOLUME_HEADER *) AllocateAlignedPages ((UINTN) EFI_SIZE_TO_PAGES ((UINTN) FvImage->FvLength), (UINTN) FvAlignment);
+ if (ProcessedFvImage == NULL) {
+ AttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INSUFFICIENT_RESOURCES;
+ Status = EFI_OUT_OF_RESOURCES;
+ break;
+ }
+ CopyMem (ProcessedFvImage, FvImage, (UINTN) FvImage->FvLength);
+ }
+
+ Status = gDS->ProcessFirmwareVolume (
+ (VOID *) ProcessedFvImage,
+ (UINTN) ProcessedFvImage->FvLength,
+ &FvProtocolHandle
+ );
+ if (EFI_ERROR (Status)) {
+ AttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INVALID_FORMAT;
+ break;
+ }
+
+ //
+ // Call the dispatcher to dispatch any drivers from the produced firmware volume
+ //
+ gDS->Dispatch ();
+ //
+ // On to the next FV in the capsule
+ //
+ Length -= (UINT32) FvImage->FvLength;
+ FvImage = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINT8 *) FvImage + FvImage->FvLength);
+ }
+
+ //
+ // Update corresponding ESRT entry LastAttemp Status
+ //
+ StatusEsrt = gBS->LocateProtocol(&gEsrtManagementProtocolGuid, NULL, (VOID **)&EsrtManagement);
+ if (!EFI_ERROR(StatusEsrt)) {
+ StatusEsrt = EsrtManagement->GetEsrtEntry(&CapsuleHeader->CapsuleGuid, &EsrtEntry);
+ if (!EFI_ERROR(StatusEsrt)){
+ //
+ // Update version can't be get from FV, set LastAttemptVersion to zero after a failed update
+ //
+ if (AttemptStatus != LAST_ATTEMPT_STATUS_SUCCESS) {
+ EsrtEntry.LastAttemptVersion = 0;
+ }
+ EsrtEntry.LastAttemptStatus = AttemptStatus;
+ EsrtManagement->UpdateEsrtEntry(&EsrtEntry);
+ }
+ }
+
+ //
+ // Indicate to sync Esrt on next boot
+ //
+ PcdSetBool(PcdEsrtSyncFmp, TRUE);
+
+ return Status;
+}
+
+
+/**
+ Convert EsrtTable physical address to virtual address
+
+ @param CapsuleHeader Points to a capsule header.
+
+ @retval EFI_SUCESS Process Capsule Image successfully.
+ @retval EFI_UNSUPPORTED Capsule image is not supported by the firmware.
+ @retval EFI_VOLUME_CORRUPTED FV volume in the capsule is corrupted.
+ @retval EFI_OUT_OF_RESOURCES Not enough memory.
+**/
+VOID
+EFIAPI
+DxeCapsuleLibVirtualAddressChangeEvent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ UINTN i;
+ EFI_CONFIGURATION_TABLE *ConfigEntry;
+
+ //
+ // Get Esrt table first
+ //
+ ConfigEntry = gST->ConfigurationTable;
+ for (i = 0 ; i < gST->NumberOfTableEntries ; i++) {
+ if (CompareGuid(&gEfiSystemResourceTableGuid, &ConfigEntry->VendorGuid)) {
+ break;
+ }
+ ConfigEntry++;
+ }
+
+ //
+ // If no Esrt table installed in Configure Table
+ //
+ if (i < gST->NumberOfTableEntries) {
+ //
+ // Search Esrt to check given capsule is qualified
+ //
+ mEsrtTable = (EFI_SYSTEM_RESOURCE_TABLE *) ConfigEntry->VendorTable;
+
+ //
+ // Update protocol pointer to Esrt Table.
+ //
+ gRT->ConvertPointer (0x00, (VOID**) &(mEsrtTable));
+ }
+
+ mIsVirtualAddrConverted = TRUE;
+
+}
+
+
+/**
+ The constructor function hook VirtualAddressChange event to use ESRT table as capsule routing table.
+
+ @param ImageHandle The firmware allocated handle for the EFI image.
+ @param SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The constructor successfully .
+ @retval Other value The constructor can't add string package.
+
+**/
+EFI_STATUS
+EFIAPI
+DxeCapsuleLibConstructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_EVENT Event;
+
+ //
+ // Make sure we can handle virtual address changes.
+ //
+ Event = NULL;
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ DxeCapsuleLibVirtualAddressChangeEvent,
+ NULL,
+ &gEfiEventVirtualAddressChangeGuid,
+ &Event
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return EFI_SUCCESS;
+}
diff --git a/Vlv2TbltDevicePkg/Library/DxeEsrtCapsuleRtLib/DxeEsrtCapsuleRtLib.inf b/Vlv2TbltDevicePkg/Library/DxeEsrtCapsuleRtLib/DxeEsrtCapsuleRtLib.inf
new file mode 100644
index 0000000000..8876b0dd01
--- /dev/null
+++ b/Vlv2TbltDevicePkg/Library/DxeEsrtCapsuleRtLib/DxeEsrtCapsuleRtLib.inf
@@ -0,0 +1,64 @@
+## @file
+# Component description file for Capsule Runtime Library
+#
+#
+# Copyright (c) 2004 - 2016, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php.
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = DxeCapsuleLib
+ FILE_GUID = 19BE1E4B-1A9A-44c1-8F12-32DD0470516A
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = CapsuleLib|DXE_RUNTIME_DRIVER
+ CONSTRUCTOR = DxeCapsuleLibConstructor
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources]
+ DxeCapsuleLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ #BpCommonPkg/BpCommonPkg.dec
+ IntelFrameworkPkg/IntelFrameworkPkg.dec
+ Vlv2TbltDevicePkg/PlatformPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ MemoryAllocationLib
+ DxeServicesTableLib
+ UefiBootServicesTableLib
+ UefiBootManagerLib
+ DevicePathLib
+
+[Pcd]
+ gPlatformModuleTokenSpaceGuid.PcdEsrtSyncFmp
+
+[Protocols]
+ gEsrtManagementProtocolGuid ## CONSUMES
+ gEfiFirmwareManagementProtocolGuid ## SOMETIMES_CONSUMES
+
+[Guids]
+ gEfiCapsuleGuid ## SOMETIMES_CONSUMED ## GUID
+ gEfiFmpCapsuleGuid ## SOMETIMES_CONSUMES ## GUID
+ gWindowsUxCapsuleGuid ## SOMETIMES_CONSUMES ## GUID
+ gEfiSystemResourceTableGuid ## SOMETIMES_CONSUMES ## GUID
+ gEfiEventVirtualAddressChangeGuid ## CONSUMES \ No newline at end of file
diff --git a/Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLib.c b/Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLib.c
index afb12c90fb..80520ef921 100644
--- a/Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLib.c
+++ b/Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLib.c
@@ -78,11 +78,11 @@ SpiFlashBlockErase (
UINT32 SpiAddress;
SpiAddress = (UINT32)(UINTN)(BaseAddress) - (UINT32)FlashDeviceBase;
- SectorSize = SECTOR_SIZE_64KB;
+ SectorSize = SECTOR_SIZE_4KB;
while ( (NumBytes > 0) && (NumBytes <= MAX_FWH_SIZE) ) {
Status = mSpiProtocol->Execute (
mSpiProtocol,
- SPI_BERASE,
+ SPI_SERASE,
SPI_WREN,
FALSE,
TRUE,
diff --git a/Vlv2TbltDevicePkg/Library/FlashDeviceLib/SpiChipDefinitions.h b/Vlv2TbltDevicePkg/Library/FlashDeviceLib/SpiChipDefinitions.h
index 15bd1e0254..a3f178fcd8 100644
--- a/Vlv2TbltDevicePkg/Library/FlashDeviceLib/SpiChipDefinitions.h
+++ b/Vlv2TbltDevicePkg/Library/FlashDeviceLib/SpiChipDefinitions.h
@@ -16,7 +16,7 @@
#include <Library/SpiFlash.H>
-#define FLASH_SIZE 0x300000
+#define FLASH_SIZE 0x400000
#define FLASH_DEVICE_BASE_ADDRESS (0xFFFFFFFF-FLASH_SIZE+1)
//
diff --git a/Vlv2TbltDevicePkg/Library/PlatformBdsLib/BdsPlatform.c b/Vlv2TbltDevicePkg/Library/PlatformBdsLib/BdsPlatform.c
index 2334c95a2c..1a3a306c7a 100644
--- a/Vlv2TbltDevicePkg/Library/PlatformBdsLib/BdsPlatform.c
+++ b/Vlv2TbltDevicePkg/Library/PlatformBdsLib/BdsPlatform.c
@@ -45,6 +45,7 @@ Abstract:
#include <Library/GenericBdsLib/String.h>
#include <Library/NetLib.h>
#include <Library/PchPlatformLib.h>
+#include <Library/CapsuleLib.h>
EFI_GUID *ConnectDriverTable[] = {
&gEfiMmioDeviceProtocolGuid,
@@ -779,6 +780,43 @@ UpdateConsoleResolution(
return;
}
+
+VOID
+EFIAPI
+PlatformBootManagerBeforeConsole (
+ VOID
+ )
+{
+ ESRT_MANAGEMENT_PROTOCOL *EsrtManagement;
+ EFI_BOOT_MODE BootMode;
+ EFI_STATUS Status;
+
+ //
+ // Require to sync ESRT from FMP in flash update boot path
+ //
+ Status = gBS->LocateProtocol(&gEsrtManagementProtocolGuid, NULL, (VOID **)&EsrtManagement);
+ if (EFI_ERROR(Status)) {
+ EsrtManagement = NULL;
+ }
+
+ if (EsrtManagement != NULL) {
+ BootMode = GetBootModeHob ();
+ DEBUG ((DEBUG_INFO, "esrtesrt!\n"));
+ if (BootMode == BOOT_ON_FLASH_UPDATE) {
+ PcdSetBool(PcdEsrtSyncFmp, TRUE);
+ }
+
+ //
+ // Lock ESRT cache repository before EndofDxe if ESRT sync is not needed
+ //
+ if (PcdGetBool(PcdEsrtSyncFmp) == FALSE) {
+ EsrtManagement->LockEsrtRepository();
+ }
+ }
+}
+
+
+
/**
Connect the predefined platform default console device. Always try to find
and enable the vga device if have.
@@ -1616,6 +1654,7 @@ PlatformBdsPolicyBehavior (
UINT16 *BootOrder;
UINTN BootOrderSize;
UINT32 DxeGpioValue;
+ ESRT_MANAGEMENT_PROTOCOL *EsrtManagement;
Timeout = PcdGet16 (PcdPlatformBootTimeOut);
if (Timeout > 10 ) {
@@ -1739,6 +1778,11 @@ PlatformBdsPolicyBehavior (
}
}
+ Status = gBS->LocateProtocol(&gEsrtManagementProtocolGuid, NULL, (VOID **)&EsrtManagement);
+ if (EFI_ERROR(Status)) {
+ EsrtManagement = NULL;
+ }
+
switch (BootMode) {
case BOOT_WITH_MINIMAL_CONFIGURATION:
@@ -1910,11 +1954,24 @@ PlatformBdsPolicyBehavior (
}
//
+ // Always sync ESRT Cache from FMP Instances after connect all and before capsule process
+ //
+ if (EsrtManagement != NULL) {
+ EsrtManagement->SyncEsrtFmp();
+ PcdSetBool(PcdEsrtSyncFmp, FALSE);
+ }
+
+ //
// Close boot script and install ready to lock
//
InstallReadyToLock ();
- ProcessCapsules (BOOT_ON_FLASH_UPDATE);
+
+ PlatformBootManagerProcessCapsules();
+
+
+ PlatformBdsLockNonUpdatableFlash ();
+
break;
case BOOT_IN_RECOVERY_MODE:
diff --git a/Vlv2TbltDevicePkg/Library/PlatformBdsLib/BdsPlatform.h b/Vlv2TbltDevicePkg/Library/PlatformBdsLib/BdsPlatform.h
index d7572435ed..9202331d84 100644
--- a/Vlv2TbltDevicePkg/Library/PlatformBdsLib/BdsPlatform.h
+++ b/Vlv2TbltDevicePkg/Library/PlatformBdsLib/BdsPlatform.h
@@ -43,6 +43,7 @@ Abstract:
#include <Protocol/MmioDevice.h>
#include <Protocol/I2cBusMcg.h>
#include <Protocol/I2cHostMcg.h>
+#include <Protocol/EsrtManagement.h>
#include <Guid/CapsuleVendor.h>
#include <Guid/MemoryTypeInformation.h>
#include <Guid/GlobalVariable.h>
@@ -450,6 +451,29 @@ BdsDeleteAllInvalidEfiBootOption (
VOID
);
+/**
+
+ This routine is called to see if there are any capsules we need to process.
+ If the boot mode is not UPDATE, then we do nothing. Otherwise find the
+ capsule HOBS and produce firmware volumes for them via the DXE service.
+ Then call the dispatcher to dispatch drivers from them. Finally, check
+ the status of the updates.
+
+ This function should be called by BDS in case we need to do some
+ sort of processing even if there is no capsule to process. We
+ need to do this if an earlier update went away and we need to
+ clear the capsule variable so on the next reset PEI does not see it and
+ think there is a capsule available.
+
+ @retval EFI_INVALID_PARAMETER boot mode is not correct for an update
+ @retval EFI_SUCCESS There is no error when processing capsule
+
+**/
+EFI_STATUS
+EFIAPI
+PlatformBootManagerProcessCapsules (
+ VOID
+ );
#define ONE_SECOND 10000000
#define FRONT_PAGE_KEY_CONTINUE 0x1000
diff --git a/Vlv2TbltDevicePkg/Library/PlatformBdsLib/Capsules.c b/Vlv2TbltDevicePkg/Library/PlatformBdsLib/Capsules.c
new file mode 100644
index 0000000000..f036c09ce7
--- /dev/null
+++ b/Vlv2TbltDevicePkg/Library/PlatformBdsLib/Capsules.c
@@ -0,0 +1,304 @@
+/** @file
+ BDS routines to handle capsules.
+
+ Copyright (c) 2004 - 2016, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+
+#include <PiDxe.h>
+
+#include <IndustryStandard/Pci.h>
+#include <IndustryStandard/PeImage.h>
+#include <IndustryStandard/Atapi.h>
+#include <IndustryStandard/Scsi.h>
+#include <IndustryStandard/WindowsUxCapsule.h>
+
+#include <Protocol/PciRootBridgeIo.h>
+#include <Protocol/BlockIo.h>
+#include <Protocol/LoadedImage.h>
+#include <Protocol/SimpleFileSystem.h>
+#include <Protocol/LoadFile.h>
+#include <Protocol/DevicePath.h>
+#include <Protocol/SimpleTextIn.h>
+#include <Protocol/SimpleTextInEx.h>
+#include <Protocol/SimpleTextOut.h>
+#include <Protocol/SimpleNetwork.h>
+#include <Protocol/FirmwareVolume2.h>
+#include <Protocol/PciIo.h>
+#include <Protocol/GraphicsOutput.h>
+#include <Protocol/UsbIo.h>
+#include <Protocol/DiskInfo.h>
+#include <Protocol/IdeControllerInit.h>
+#include <Protocol/BootLogo.h>
+#include <Protocol/DriverHealth.h>
+#include <Protocol/FormBrowser2.h>
+#include <Protocol/EsrtManagement.h>
+
+#include <Guid/MemoryTypeInformation.h>
+#include <Guid/FileInfo.h>
+#include <Guid/GlobalVariable.h>
+#include <Guid/Performance.h>
+#include <Guid/StatusCodeDataTypeVariable.h>
+#include <Guid/FmpCapsule.h>
+
+#include <Library/PrintLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/UefiLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/HobLib.h>
+#include <Library/BaseLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/PerformanceLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PeCoffGetEntryPointLib.h>
+#include <Library/UefiBootManagerLib.h>
+#include <Library/TimerLib.h>
+#include <Library/DxeServicesLib.h>
+#include <Library/ReportStatusCodeLib.h>
+#include <Library/CapsuleLib.h>
+#include <Library/PerformanceLib.h>
+#include <Library/HiiLib.h>
+
+/**
+
+ This routine is called to see if there are any capsules we need to process.
+ If the boot mode is not UPDATE, then we do nothing. Otherwise find the
+ capsule HOBS and produce firmware volumes for them via the DXE service.
+ Then call the dispatcher to dispatch drivers from them. Finally, check
+ the status of the updates.
+
+ This function should be called by BDS in case we need to do some
+ sort of processing even if there is no capsule to process. We
+ need to do this if an earlier update went away and we need to
+ clear the capsule variable so on the next reset PEI does not see it and
+ think there is a capsule available.
+
+ @retval EFI_INVALID_PARAMETER boot mode is not correct for an update
+ @retval EFI_SUCCESS There is no error when processing capsule
+
+**/
+EFI_STATUS
+EFIAPI
+PlatformBootManagerProcessCapsules (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_PEI_HOB_POINTERS HobPointer;
+ EFI_CAPSULE_HEADER *CapsuleHeader;
+ UINT32 Size;
+ UINT32 CapsuleNumber;
+ UINT32 CapsuleTotalNumber;
+ EFI_CAPSULE_TABLE *CapsuleTable;
+ UINT32 Index;
+ UINT32 CacheIndex;
+ UINT32 CacheNumber;
+ VOID **CapsulePtr;
+ VOID **CapsulePtrCache;
+ EFI_GUID *CapsuleGuidCache;
+ BOOLEAN ColdReboot;
+ ESRT_MANAGEMENT_PROTOCOL *EsrtManagement;
+
+ CapsuleNumber = 0;
+ CapsuleTotalNumber = 0;
+ CacheIndex = 0;
+ CacheNumber = 0;
+ ColdReboot = FALSE;
+ CapsulePtr = NULL;
+ CapsulePtrCache = NULL;
+ CapsuleGuidCache = NULL;
+ EsrtManagement = NULL;
+
+
+ //
+ // We don't do anything else if the boot mode is not flash-update
+ //
+ ASSERT (GetBootModeHob () == BOOT_ON_FLASH_UPDATE);
+
+ Status = EFI_SUCCESS;
+ //
+ // Find all capsule images from hob
+ //
+ HobPointer.Raw = GetHobList ();
+ while ((HobPointer.Raw = GetNextHob (EFI_HOB_TYPE_UEFI_CAPSULE, HobPointer.Raw)) != NULL) {
+ CapsuleTotalNumber ++;
+ HobPointer.Raw = GET_NEXT_HOB (HobPointer);
+ }
+
+ if (CapsuleTotalNumber == 0) {
+ //
+ // We didn't find a hob, so had no errors.
+ //
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Init temp Capsule Data table.
+ //
+ CapsulePtr = (VOID **) AllocateZeroPool (sizeof (VOID *) * CapsuleTotalNumber);
+ ASSERT (CapsulePtr != NULL);
+ CapsulePtrCache = (VOID **) AllocateZeroPool (sizeof (VOID *) * CapsuleTotalNumber);
+ ASSERT (CapsulePtrCache != NULL);
+ CapsuleGuidCache = (EFI_GUID *) AllocateZeroPool (sizeof (EFI_GUID) * CapsuleTotalNumber);
+ ASSERT (CapsuleGuidCache != NULL);
+
+ //
+ // Find all capsule images from hob
+ //
+ HobPointer.Raw = GetHobList ();
+ while ((HobPointer.Raw = GetNextHob (EFI_HOB_TYPE_UEFI_CAPSULE, HobPointer.Raw)) != NULL) {
+ CapsulePtr [CapsuleNumber++] = (VOID *) (UINTN) HobPointer.Capsule->BaseAddress;
+ HobPointer.Raw = GET_NEXT_HOB (HobPointer);
+ }
+
+ //
+ //Check the capsule flags,if contains CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE, install
+ //capsuleTable to configure table with EFI_CAPSULE_GUID
+ //
+
+ //
+ // Capsules who have CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE always are used for operating
+ // System to have information persist across a system reset. EFI System Table must
+ // point to an array of capsules that contains the same CapsuleGuid value. And agents
+ // searching for this type capsule will look in EFI System Table and search for the
+ // capsule's Guid and associated pointer to retrieve the data. Two steps below describes
+ // how to sorting the capsules by the unique guid and install the array to EFI System Table.
+ // Firstly, Loop for all coalesced capsules, record unique CapsuleGuids and cache them in an
+ // array for later sorting capsules by CapsuleGuid.
+ //
+ for (Index = 0; Index < CapsuleTotalNumber; Index++) {
+ CapsuleHeader = (EFI_CAPSULE_HEADER*) CapsulePtr [Index];
+ if ((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) != 0) {
+ //
+ // For each capsule, we compare it with known CapsuleGuid in the CacheArray.
+ // If already has the Guid, skip it. Whereas, record it in the CacheArray as
+ // an additional one.
+ //
+ CacheIndex = 0;
+ while (CacheIndex < CacheNumber) {
+ if (CompareGuid(&CapsuleGuidCache[CacheIndex],&CapsuleHeader->CapsuleGuid)) {
+ break;
+ }
+ CacheIndex++;
+ }
+ if (CacheIndex == CacheNumber) {
+ CopyMem(&CapsuleGuidCache[CacheNumber++],&CapsuleHeader->CapsuleGuid,sizeof(EFI_GUID));
+ }
+ }
+ }
+
+ //
+ // Secondly, for each unique CapsuleGuid in CacheArray, gather all coalesced capsules
+ // whose guid is the same as it, and malloc memory for an array which preceding
+ // with UINT32. The array fills with entry point of capsules that have the same
+ // CapsuleGuid, and UINT32 represents the size of the array of capsules. Then install
+ // this array into EFI System Table, so that agents searching for this type capsule
+ // will look in EFI System Table and search for the capsule's Guid and associated
+ // pointer to retrieve the data.
+ //
+ CacheIndex = 0;
+ while (CacheIndex < CacheNumber) {
+ CapsuleNumber = 0;
+ for (Index = 0; Index < CapsuleTotalNumber; Index++) {
+ CapsuleHeader = (EFI_CAPSULE_HEADER*) CapsulePtr [Index];
+ if ((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) != 0) {
+ if (CompareGuid (&CapsuleGuidCache[CacheIndex], &CapsuleHeader->CapsuleGuid)) {
+ //
+ // Cache Caspuleheader to the array, this array is uniqued with certain CapsuleGuid.
+ //
+ CapsulePtrCache[CapsuleNumber++] = (VOID*)CapsuleHeader;
+ }
+ }
+ }
+ if (CapsuleNumber != 0) {
+ Size = sizeof(EFI_CAPSULE_TABLE) + (CapsuleNumber - 1) * sizeof(VOID*);
+ CapsuleTable = AllocateRuntimePool (Size);
+ ASSERT (CapsuleTable != NULL);
+ CapsuleTable->CapsuleArrayNumber = CapsuleNumber;
+ CopyMem(&CapsuleTable->CapsulePtr[0], CapsulePtrCache, CapsuleNumber * sizeof(VOID*));
+ Status = gBS->InstallConfigurationTable (&CapsuleGuidCache[CacheIndex], (VOID*)CapsuleTable);
+ ASSERT_EFI_ERROR (Status);
+ }
+ CacheIndex++;
+ }
+
+
+ //
+ // Besides ones with CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE flag, if Windows UX capsule exist, process it first
+ //
+ for (Index = 0; Index < CapsuleTotalNumber; Index++) {
+ CapsuleHeader = (EFI_CAPSULE_HEADER*) CapsulePtr [Index];
+ if ((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) == 0
+ && CompareGuid(&CapsuleHeader->CapsuleGuid ,&gWindowsUxCapsuleGuid)) {
+ ProcessCapsuleImage (CapsuleHeader);
+ break;
+ }
+ }
+
+ //
+ // Besides ones with CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE flag, all capsules left are
+ // recognized by platform.
+ //
+ for (Index = 0; Index < CapsuleTotalNumber; Index++) {
+ CapsuleHeader = (EFI_CAPSULE_HEADER*) CapsulePtr [Index];
+ if ((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) == 0
+ && !CompareGuid(&CapsuleHeader->CapsuleGuid ,&gWindowsUxCapsuleGuid)) {
+ //
+ // Call capsule library to process capsule image.
+ //
+ ProcessCapsuleImage (CapsuleHeader);
+ if ((CapsuleHeader->Flags & PcdGet16(PcdSystemRebootAfterCapsuleProcessFlag)) != 0 ||
+ CompareGuid(&CapsuleHeader->CapsuleGuid ,&gEfiFmpCapsuleGuid)) {
+ ColdReboot = TRUE;
+ }
+ }
+ }
+
+ //
+ // Reboot System if required after all capsule processed
+ //
+ if (ColdReboot) {
+
+ DEBUG ((DEBUG_INFO, "Cold Reset after process capsule!\n"));
+ gRT->ResetSystem(EfiResetCold, EFI_SUCCESS, 0, NULL);
+ CpuDeadLoop ();
+ }
+
+ //
+ // Free the allocated temp memory space.
+ //
+ FreePool (CapsuleGuidCache);
+ FreePool (CapsulePtrCache);
+ FreePool (CapsulePtr);
+
+ Status = gBS->LocateProtocol(&gEsrtManagementProtocolGuid, NULL, (VOID **)&EsrtManagement);
+ //
+ // Always sync ESRT Cache from FMP Instance after Connect All
+ //
+ if (!EFI_ERROR(Status)) {
+ //
+ // Reconnect all & sync ESRT from FMP
+ //
+ EfiBootManagerConnectAll ();
+
+ Status = EsrtManagement->SyncEsrtFmp();
+ } else {
+ Status = EFI_SUCCESS;
+ }
+
+ return Status;
+}
+
diff --git a/Vlv2TbltDevicePkg/Library/PlatformBdsLib/PlatformBdsLib.inf b/Vlv2TbltDevicePkg/Library/PlatformBdsLib/PlatformBdsLib.inf
index ff5edc31c5..5778f697c6 100644
--- a/Vlv2TbltDevicePkg/Library/PlatformBdsLib/PlatformBdsLib.inf
+++ b/Vlv2TbltDevicePkg/Library/PlatformBdsLib/PlatformBdsLib.inf
@@ -38,6 +38,7 @@
BdsPlatform.h
PlatformData.c
PlatformBdsStrings.uni
+ Capsules.c
[Packages]
MdePkg/MdePkg.dec
@@ -73,6 +74,7 @@
S3BootScriptLib
SerialPortLib
PchPlatformLib
+ UefiBootManagerLib
[Protocols]
gEfiFirmwareVolume2ProtocolGuid
@@ -91,6 +93,7 @@
gEfiMmioDeviceProtocolGuid
gEfiI2cMasterProtocolGuid
gEfiI2cHostProtocolGuid
+ gEsrtManagementProtocolGuid ## SOMETIMES_CONSUME
[Guids]
gEfiMemoryTypeInformationGuid
@@ -98,6 +101,7 @@
gEfiGlobalVariableGuid
gEfiNormalSetupGuid
gEfiPartTypeSystemPartGuid
+ gWindowsUxCapsuleGuid
[Pcd]
gPlatformModuleTokenSpaceGuid.PcdFlashFvRecovery2Base
@@ -119,3 +123,5 @@
gEfiMdeModulePkgTokenSpaceGuid.PcdSetupVideoHorizontalResolution
gEfiMdeModulePkgTokenSpaceGuid.PcdSetupVideoVerticalResolution
gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdBootState
+ gPlatformModuleTokenSpaceGuid.PcdEsrtSyncFmp
+ gEfiMdeModulePkgTokenSpaceGuid.PcdSystemRebootAfterCapsuleProcessFlag ## CONSUMES
diff --git a/Vlv2TbltDevicePkg/PlatformEsrt/PlatformEsrtDxe.c b/Vlv2TbltDevicePkg/PlatformEsrt/PlatformEsrtDxe.c
new file mode 100644
index 0000000000..ee2def8c80
--- /dev/null
+++ b/Vlv2TbltDevicePkg/PlatformEsrt/PlatformEsrtDxe.c
@@ -0,0 +1,140 @@
+/** @file
+ Non-FMP ESRT Platform Driver to produce system firmware resource to ESRT
+
+ Copyright (c) 2004 - 2016, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ 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 "PlatformEsrtDxe.h"
+
+
+
+EFI_SYSTEM_RESOURCE_ENTRY EsrtTemplateBuf[] = {
+ // System Firmware Entry
+ {
+ SYSTEM_FW_CLASS_GUID,
+ ESRT_FW_TYPE_SYSTEMFIRMWARE,
+ 0x0001,
+ 0x0001,
+ 0x0000,
+ 0x0000,
+ LAST_ATTEMPT_STATUS_SUCCESS
+ }
+};
+
+UINTN EsrtCount = sizeof(EsrtTemplateBuf) / sizeof(EFI_SYSTEM_RESOURCE_ENTRY);
+
+
+/**
+ Register all platform updatable firmware resourece to Esrt table
+
+ @param[in] Event The Event that is being processed.
+ @param[in] Context The Event Context.
+
+**/
+EFI_STATUS
+RegisterPlatformEsrtEntry()
+{
+ EFI_STATUS Status;
+ ESRT_MANAGEMENT_PROTOCOL *EsrtManagement;
+ UINTN Index;
+
+ Status = gBS->LocateProtocol(&gEsrtManagementProtocolGuid, NULL, (VOID **)&EsrtManagement);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ for (Index = 0; Index < EsrtCount; Index++) {
+ Status = EsrtManagement->GetEsrtEntry(
+ &EsrtTemplateBuf[Index].FwClass,
+ &EsrtTemplateBuf[Index]
+ );
+ if (Status == EFI_NOT_FOUND) {
+ //
+ // Init EsrtEntry for system firmware updatable resource
+ //
+ Status = EsrtManagement->RegisterEsrtEntry(&EsrtTemplateBuf[Index]);
+ }
+ }
+
+ return Status;
+
+}
+
+
+/**
+ Notify function for protocol ESRT management protocol. This is used to
+ register system firmware updatable resourece to Esrt table
+
+ @param[in] Event The Event that is being processed.
+ @param[in] Context The Event Context.
+
+**/
+VOID
+EFIAPI
+PlatformEsrtNotifyFunction (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+
+ Status = RegisterPlatformEsrtEntry();
+ DEBUG ((EFI_D_INFO, "PlatformEsrtDxe Status = 0x%x\n", Status));
+}
+
+
+EFI_STATUS
+EFIAPI
+PlatformEsrtDxeEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_EVENT Event;
+ VOID *Registration;
+ ESRT_MANAGEMENT_PROTOCOL *EsrtManagement;
+ UINTN Index;
+
+ for (Index = 0; Index < EsrtCount; Index++) {
+ EsrtTemplateBuf[Index].CapsuleFlags = PcdGet16(PcdSystemRebootAfterCapsuleProcessFlag);
+ }
+
+ Status = gBS->LocateProtocol(&gEsrtManagementProtocolGuid, NULL, (VOID **)&EsrtManagement);
+ if (!EFI_ERROR(Status)) {
+ //
+ // Directly Register Platform Updatable Resource
+ //
+ return RegisterPlatformEsrtEntry();
+ }
+
+ //
+ // Register Callback function for updating USB Rmrr address
+ //
+ Status = gBS->CreateEvent (
+ EVT_NOTIFY_SIGNAL,
+ TPL_CALLBACK,
+ PlatformEsrtNotifyFunction,
+ NULL,
+ &Event
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = gBS->RegisterProtocolNotify(
+ &gEsrtManagementProtocolGuid,
+ Event,
+ &Registration
+ );
+
+ return EFI_SUCCESS;
+}
diff --git a/Vlv2TbltDevicePkg/PlatformEsrt/PlatformEsrtDxe.h b/Vlv2TbltDevicePkg/PlatformEsrt/PlatformEsrtDxe.h
new file mode 100644
index 0000000000..bcf1bc80be
--- /dev/null
+++ b/Vlv2TbltDevicePkg/PlatformEsrt/PlatformEsrtDxe.h
@@ -0,0 +1,32 @@
+/** @file
+ Header file for Non-FMP platform ESRT driver
+
+ Copyright (c) 2004 - 2016, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ 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 _EFI_PLATFORM_ESRT_DXE_H_
+#define _EFI_PLATFORM_ESRT_DXE_H_
+
+#include <Guid/SystemResourceTable.h>
+#include <Guid/SystemFwClassGuid.h>
+
+#include <Library/PrintLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/DebugLib.h>
+
+#include <Protocol/EsrtManagement.h>
+
+#endif // #ifndef _EFI_PLATFORM_ESRT_DXE_H_
diff --git a/Vlv2TbltDevicePkg/PlatformEsrt/PlatformEsrtDxe.inf b/Vlv2TbltDevicePkg/PlatformEsrt/PlatformEsrtDxe.inf
new file mode 100644
index 0000000000..6ee110542c
--- /dev/null
+++ b/Vlv2TbltDevicePkg/PlatformEsrt/PlatformEsrtDxe.inf
@@ -0,0 +1,58 @@
+## @file
+# Component description file for platform ESRT module
+#
+#
+# Copyright (c) 2004 - 2016, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# 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 = PlatformEsrtDxe
+ FILE_GUID = 0484EBBA-7D8F-48ae-8F98-A77E0961DEEA
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = PlatformEsrtDxeEntryPoint
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources]
+ PlatformEsrtDxe.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ Vlv2TbltDevicePkg/PlatformPkg.dec
+
+[LibraryClasses]
+ UefiDriverEntryPoint
+ BaseLib
+ BaseMemoryLib
+ MemoryAllocationLib
+ UefiLib
+ UefiBootServicesTableLib
+ UefiRuntimeServicesTableLib
+ DebugLib
+ PrintLib
+ PcdLib
+
+[Pcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdSystemRebootAfterCapsuleProcessFlag ## CONSUMES
+
+[Protocols]
+ gEsrtManagementProtocolGuid ## CONSUMES
+
+[Guids]
+ gSystemFwClassGuid \ No newline at end of file
diff --git a/Vlv2TbltDevicePkg/PlatformPkg.dec b/Vlv2TbltDevicePkg/PlatformPkg.dec
index 642bcf92a3..ea84a93b1f 100644
--- a/Vlv2TbltDevicePkg/PlatformPkg.dec
+++ b/Vlv2TbltDevicePkg/PlatformPkg.dec
@@ -64,6 +64,8 @@
gFirmwareIdGuid = { 0x5e559c23, 0x1faa, 0x4ae1, { 0x8d, 0x4a, 0xc6, 0xcf, 0x02, 0x6c, 0x76, 0x6f } }
gBmpImageGuid = { 0x878AC2CC, 0x5343, 0x46F2, { 0xB5, 0x63, 0x51, 0xF8, 0x9D, 0xAF, 0x56, 0xBA } }
gOsSelectionVariableGuid = { 0x86843f56, 0x675d, 0x40a5, { 0x95, 0x30, 0xbc, 0x85, 0x83, 0x72, 0xf1, 0x03 } }
+ gFMPSampleUpdateImageInfoGuid = { 0xb9847c4e, 0xf5b6, 0x42dc, { 0xb6, 0xf4, 0xed, 0x44, 0x7, 0xb0, 0x67, 0x4c }}
+ gSystemFwClassGuid = { 0x819b858e, 0xc52c, 0x402f, { 0x80, 0xe1, 0x5b, 0x31, 0x1b, 0x6c, 0x19, 0x59 } }
[Protocols]
gEfiActiveBiosProtocolGuid = { 0xebbe2d1b, 0x1647, 0x4bda, { 0xab, 0x9a, 0x78, 0x63, 0xe3, 0x96, 0xd4, 0x1a } }
@@ -155,6 +157,7 @@
gPlatformModuleTokenSpaceGuid.PcdTxeRomSize|0x003FF000|UINT32|0x4000000A
gPlatformModuleTokenSpaceGuid.PcdBiosRomBase|0xFFC00000|UINT32|0x4000000B
gPlatformModuleTokenSpaceGuid.PcdBiosRomSize|0x00400000|UINT32|0x4000000C
+ gPlatformModuleTokenSpaceGuid.PcdFlashMinEraseSize|0x1000|UINT32|0x70000007
[PcdsFeatureFlag]
## This PCD specifies whether StatusCode is reported via ISA Serial port.
@@ -171,11 +174,16 @@
#new added feature for BIOS usb recovery
gEfiIchTokenSpaceGuid.PcdEhciRecoveryEnabled|TRUE|BOOLEAN|0x00000026
+
+ gPlatformModuleTokenSpaceGuid.PcdFeatureRecoveryDisabled|FALSE|BOOLEAN|0x20005004
[PcdsDynamic,PcdsDynamicEx]
gPlatformModuleTokenSpaceGuid.PcdInConfigMode|FALSE|BOOLEAN|0x80000001
gPlatformModuleTokenSpaceGuid.PcdConnectUSBKeyboardonWaitForKeyStroke|FALSE|BOOLEAN|0x80000002
gPlatformModuleTokenSpaceGuid.PcdEnableWatchdogSwSmiInputValue|0|UINT8|0x80000003
+ ## Indicates platform to sync ESRT repository from FMP instances
+ gPlatformModuleTokenSpaceGuid.PcdEsrtSyncFmp|TRUE|BOOLEAN|0x80000004
+
#
#device firmware update support
#
@@ -198,11 +206,11 @@
gEfiSpiProtocolGuid = { 0x1156efc6, 0xea32, 0x4396, { 0xb5, 0xd5, 0x26, 0x93, 0x2e, 0x83, 0xc3, 0x13 }}
gEfiGpioOperationProtocolGuid = { 0x38DDFE8F, 0x8991, 0x44AA, { 0x98, 0x89, 0x83, 0xF4, 0x91, 0x84, 0x65, 0xB0 }}
gEfiEsrtOperationProtocolGuid = { 0x4549AB47, 0x6E60, 0x4293, { 0xB9, 0x1D, 0x31, 0xB6, 0x10, 0xAD, 0x80, 0x56 }}
-
+
[Guids]
gEfiFwDisplayCapsuleGuid = { 0x3b8c8162, 0x188c, 0x46a4, { 0xae, 0xc9, 0xbe, 0x43, 0xf1, 0xd6, 0x56, 0x97 } }
gEfiFirmwareClassGuid = { 0xb122a262, 0x3551, 0x4f48, { 0x88, 0x92, 0x55, 0xf6, 0xc0, 0x61, 0x42, 0x90 } }
gEfiDFUVerGuid = { 0x0dc73aed, 0xcbf6, 0x4a25, { 0xa6, 0x8d, 0x59, 0xc8, 0x0f, 0x44, 0xc7, 0xc3 } }
gEfiEsrtTableGuid = { 0xb122a263, 0x3661, 0x4f68, { 0x99, 0x29, 0x78, 0xf8, 0xb0, 0xd6, 0x21, 0x80 } }
gEfiCapsuleCrashLogVarGuid = { 0xf3ff1468, 0x04ba, 0x4966, { 0x9f, 0xb2, 0xe4, 0xa7, 0x90, 0x05, 0x46, 0x50 } }
- gEfiCapsuleCrashGuid = { 0x0e1d2972, 0x65af, 0x4ac1, { 0xbf, 0xa3, 0xce, 0xf4, 0xab, 0x0c, 0x38, 0xfe } }
+ gEfiCapsuleCrashGuid = { 0x0e1d2972, 0x65af, 0x4ac1, { 0xbf, 0xa3, 0xce, 0xf4, 0xab, 0x0c, 0x38, 0xfe } } \ No newline at end of file
diff --git a/Vlv2TbltDevicePkg/PlatformPkg.fdf b/Vlv2TbltDevicePkg/PlatformPkg.fdf
index 3432904825..066cb75ba2 100644
--- a/Vlv2TbltDevicePkg/PlatformPkg.fdf
+++ b/Vlv2TbltDevicePkg/PlatformPkg.fdf
@@ -48,10 +48,10 @@ DEFINE FLASH_REGION_AZALIABIN_BASE = 0xFFD08000
!endif
DEFINE FLASH_REGION_FVMAIN_OFFSET = 0x00110000
-DEFINE FLASH_REGION_FVMAIN_SIZE = 0x00215000
+DEFINE FLASH_REGION_FVMAIN_SIZE = 0x00210000
-DEFINE FLASH_REGION_FV_RECOVERY2_OFFSET = 0x00325000
-DEFINE FLASH_REGION_FV_RECOVERY2_SIZE = 0x0006B000
+DEFINE FLASH_REGION_FV_RECOVERY2_OFFSET = 0x00320000
+DEFINE FLASH_REGION_FV_RECOVERY2_SIZE = 0x00070000
DEFINE FLASH_REGION_FV_RECOVERY_OFFSET = 0x00390000
DEFINE FLASH_REGION_FV_RECOVERY_SIZE = 0x00070000
@@ -358,9 +358,13 @@ INF RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET
!if $(CAPSULE_ENABLE) == TRUE
+!if $(DXE_ARCHITECTURE) == X64
INF MdeModulePkg/Universal/CapsulePei/CapsulePei.inf
!if $(DXE_ARCHITECTURE) == "X64"
INF MdeModulePkg/Universal/CapsulePei/CapsuleX64.inf
+!else
+INF MdeModulePkg/Universal/CapsulePei/CapsulePei.inf
+!endif
!endif
!endif
@@ -719,6 +723,12 @@ FILE FREEFORM = 878AC2CC-5343-46F2-B563-51F89DAF56BA {
!endif
!endif
+!if $(ESRT_ENABLE) == TRUE
+ INF MdeModulePkg/Universal/EsrtDxe/EsrtDxe.inf
+ INF $(PLATFORM_PACKAGE)/PlatformEsrt/PlatformEsrtDxe.inf
+ INF $(PLATFORM_PACKAGE)/FmpSample/FmpSample.inf
+!endif
+
[FV.FVMAIN_COMPACT]
BlockSize = $(FLASH_BLOCK_SIZE)
FvAlignment = 16
@@ -738,8 +748,6 @@ READ_STATUS = TRUE
READ_LOCK_CAP = TRUE
READ_LOCK_STATUS = TRUE
-
-
FILE FV_IMAGE = 9E21FD93-9C72-4c15-8C4B-E77F1DB2D792 {
!if $(LZMA_ENABLE) == TRUE
# LZMA Compress
@@ -782,7 +790,7 @@ READ_LOCK_CAP = TRUE
READ_LOCK_STATUS = TRUE
-[FV.Update_Data]
+[FV.Bios_Update_Data]
BlockSize = $(FLASH_BLOCK_SIZE)
FvAlignment = 16
ERASE_POLARITY = 1
@@ -801,8 +809,8 @@ READ_STATUS = TRUE
READ_LOCK_CAP = TRUE
READ_LOCK_STATUS = TRUE
-FILE RAW = 88888888-8888-8888-8888-888888888888 {
- FD = Vlv
+FILE FV_IMAGE = 4A538818-5AE0-4eb2-B2EB-488B23657022 {
+ SECTION FV_IMAGE = FVMAIN_COMPACT
}
[FV.BiosUpdateCargo]
@@ -824,6 +832,17 @@ READ_STATUS = TRUE
READ_LOCK_CAP = TRUE
READ_LOCK_STATUS = TRUE
+!if $(ESRT_ENABLE) == TRUE
+ INF $(PLATFORM_PACKAGE)/UpdateDriverDxe/UpdateDriverDxe.inf
+!else
+ INF IntelFrameworkModulePkg/Universal/FirmwareVolume/UpdateDriverDxe/UpdateDriverDxe.inf
+!endif
+FILE RAW = 283FA2EE-532C-484d-9383-9F93B36F0B7E {
+ FV = Bios_Update_Data
+ }
+FILE RAW = 98B8D59B-E8BA-48EE-98DD-C295392F1EDB {
+ Vlv2TbltDevicePkg/BiosUpdateConfig/BiosUpdateConfig.ini
+ }
[FV.BiosUpdate]
@@ -845,23 +864,33 @@ READ_STATUS = TRUE
READ_LOCK_CAP = TRUE
READ_LOCK_STATUS = TRUE
+FILE FV_IMAGE = EDBEDF47-6EA3-4512-83C1-70F4769D4BDE {
+ SECTION GUIDED {
+ SECTION FV_IMAGE = BiosUpdateCargo
+ }
+ }
+
[Capsule.Capsule_Boot]
-#
-# gEfiCapsuleGuid supported by platform
-# { 0x3B6686BD, 0x0D76, 0x4030, { 0xB7, 0x0E, 0xB5, 0x51, 0x9E, 0x2F, 0xC5, 0xA0 }}
-#
-CAPSULE_GUID = 3B6686BD-0D76-4030-B70E-B5519E2FC5A0
-CAPSULE_FLAGS = PersistAcrossReset
+!if $(ESRT_ENABLE) == TRUE
+CAPSULE_GUID = 819b858e-c52c-402f-80e1-5b311b6c1959
+!else
+CAPSULE_GUID = 3B6686BD-0D76-4030-B70E-B5519E2FC5A0
+!endif
+
+CAPSULE_FLAGS = PersistAcrossReset, InitiateReset
+OEM_CAPSULE_FLAGS = 0x0001
+
CAPSULE_HEADER_SIZE = 0x20
FV = BiosUpdate
[Capsule.Capsule_Reset]
-#
-# gEfiCapsuleGuid supported by platform
-# { 0x3B6686BD, 0x0D76, 0x4030, { 0xB7, 0x0E, 0xB5, 0x51, 0x9E, 0x2F, 0xC5, 0xA0 }}
-#
-CAPSULE_GUID = 3B6686BD-0D76-4030-B70E-B5519E2FC5A0
+!if $(ESRT_ENABLE) == TRUE
+CAPSULE_GUID = 819b858e-c52c-402f-80e1-5b311b6c1959
+!else
+CAPSULE_GUID = 3B6686BD-0D76-4030-B70E-B5519E2FC5A0
+!endif
+
CAPSULE_FLAGS = PersistAcrossReset
CAPSULE_HEADER_SIZE = 0x20
diff --git a/Vlv2TbltDevicePkg/PlatformPkgConfig.dsc b/Vlv2TbltDevicePkg/PlatformPkgConfig.dsc
index db50b9322a..0ad8b4a538 100644
--- a/Vlv2TbltDevicePkg/PlatformPkgConfig.dsc
+++ b/Vlv2TbltDevicePkg/PlatformPkgConfig.dsc
@@ -1,97 +1,98 @@
-#/** @file
-# platform configuration file.
-#
-# Copyright (c) 2012 - 2015, Intel Corporation. All rights reserved.<BR>
-#
-# This program and the accompanying materials are licensed and made available under
-# the terms and conditions of the BSD License that accompanies this distribution.
-# The full text of the license may be found at
-# http://opensource.org/licenses/bsd-license.php.
-#
-# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-#
-#
-#**/
-
-#
-# TRUE is ENABLE. FASLE is DISABLE.
-#
-
-#
-# FSP selection
-#
-DEFINE MINNOW2_FSP_BUILD = FALSE
-
-
-DEFINE SCSI_ENABLE = TRUE
-
-
-#
-# To enable extra configuration for clk gen
-#
-DEFINE CLKGEN_CONFIG_EXTRA_ENABLE=TRUE
-
-#
-# Feature selection
-#
-
-#
-# Select system timer which is used to produce Timer Arch Protocol:
-# TRUE - HPET timer is used.
-# FALSE - 8254 timer is used.
-#
-DEFINE USE_HPET_TIMER = FALSE
-
-
-#
-# Feature selection
-#
-
-DEFINE TPM_ENABLED = FALSE
-
-DEFINE ACPI50_ENABLE = TRUE
-DEFINE PERFORMANCE_ENABLE = FALSE
-
-
-DEFINE LFMA_ENABLE = FALSE # Load module at fixed address feature
-DEFINE DXE_COMPRESS_ENABLE = TRUE
-DEFINE DXE_CRC32_SECTION_ENABLE = TRUE
-DEFINE SSE2_ENABLE = FALSE
-
-DEFINE SECURE_BOOT_ENABLE = TRUE
-DEFINE USER_IDENTIFICATION_ENABLE = FALSE
-DEFINE VARIABLE_INFO_ENABLE = FALSE
-DEFINE S3_ENABLE = TRUE
-DEFINE CAPSULE_ENABLE = FALSE
-DEFINE CAPSULE_RESET_ENABLE = TRUE
-
-DEFINE GOP_DRIVER_ENABLE = TRUE
-DEFINE DATAHUB_ENABLE = TRUE
-DEFINE DATAHUB_STATUS_CODE_ENABLE = TRUE
-DEFINE USB_ENABLE = TRUE
-
-DEFINE ISA_SERIAL_STATUS_CODE_ENABLE = TRUE
-DEFINE USB_SERIAL_STATUS_CODE_ENABLE = FALSE
-DEFINE RAM_SERIAL_STATUS_CODE_ENABLE = FALSE
-
-DEFINE ENBDT_S3_SUPPORT = TRUE
-
-DEFINE LZMA_ENABLE = TRUE
-DEFINE S4_ENABLE = TRUE
-DEFINE NETWORK_ENABLE = TRUE
-DEFINE NETWORK_IP6_ENABLE = TRUE
-DEFINE NETWORK_ISCSI_ENABLE = FALSE
-DEFINE NETWORK_VLAN_ENABLE = FALSE
-
-DEFINE SATA_ENABLE = TRUE
-DEFINE PCIESC_ENABLE = TRUE
-
-#
-# Enable source level debug default
-#
-DEFINE SOURCE_DEBUG_ENABLE = FALSE
-
-
-
-
+#/** @file
+# platform configuration file.
+#
+# Copyright (c) 2012 - 2015, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License that accompanies this distribution.
+# The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php.
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#
+#**/
+
+#
+# TRUE is ENABLE. FASLE is DISABLE.
+#
+
+#
+# FSP selection
+#
+DEFINE MINNOW2_FSP_BUILD = FALSE
+
+
+DEFINE SCSI_ENABLE = TRUE
+
+
+#
+# To enable extra configuration for clk gen
+#
+DEFINE CLKGEN_CONFIG_EXTRA_ENABLE=TRUE
+
+#
+# Feature selection
+#
+
+#
+# Select system timer which is used to produce Timer Arch Protocol:
+# TRUE - HPET timer is used.
+# FALSE - 8254 timer is used.
+#
+DEFINE USE_HPET_TIMER = FALSE
+
+
+#
+# Feature selection
+#
+
+DEFINE TPM_ENABLED = FALSE
+
+DEFINE ACPI50_ENABLE = TRUE
+DEFINE PERFORMANCE_ENABLE = FALSE
+
+
+DEFINE LFMA_ENABLE = FALSE # Load module at fixed address feature
+DEFINE DXE_COMPRESS_ENABLE = TRUE
+DEFINE DXE_CRC32_SECTION_ENABLE = TRUE
+DEFINE SSE2_ENABLE = FALSE
+
+DEFINE SECURE_BOOT_ENABLE = TRUE
+DEFINE USER_IDENTIFICATION_ENABLE = FALSE
+DEFINE VARIABLE_INFO_ENABLE = FALSE
+DEFINE S3_ENABLE = TRUE
+DEFINE CAPSULE_ENABLE = TRUE
+DEFINE CAPSULE_RESET_ENABLE = TRUE
+
+DEFINE GOP_DRIVER_ENABLE = TRUE
+DEFINE DATAHUB_ENABLE = TRUE
+DEFINE DATAHUB_STATUS_CODE_ENABLE = TRUE
+DEFINE USB_ENABLE = TRUE
+
+DEFINE ISA_SERIAL_STATUS_CODE_ENABLE = TRUE
+DEFINE USB_SERIAL_STATUS_CODE_ENABLE = FALSE
+DEFINE RAM_SERIAL_STATUS_CODE_ENABLE = FALSE
+
+DEFINE ENBDT_S3_SUPPORT = TRUE
+
+DEFINE LZMA_ENABLE = TRUE
+DEFINE S4_ENABLE = TRUE
+DEFINE NETWORK_ENABLE = TRUE
+DEFINE NETWORK_IP6_ENABLE = TRUE
+DEFINE NETWORK_ISCSI_ENABLE = FALSE
+DEFINE NETWORK_VLAN_ENABLE = FALSE
+
+DEFINE SATA_ENABLE = TRUE
+DEFINE PCIESC_ENABLE = TRUE
+DEFINE ESRT_ENABLE = TRUE
+
+#
+# Enable source level debug default
+#
+DEFINE SOURCE_DEBUG_ENABLE = FALSE
+
+
+
+
diff --git a/Vlv2TbltDevicePkg/PlatformPkgGcc.fdf b/Vlv2TbltDevicePkg/PlatformPkgGcc.fdf
index 3326fb2925..d519edd4c8 100644
--- a/Vlv2TbltDevicePkg/PlatformPkgGcc.fdf
+++ b/Vlv2TbltDevicePkg/PlatformPkgGcc.fdf
@@ -676,6 +676,12 @@ FILE FREEFORM = 878AC2CC-5343-46F2-B563-51F89DAF56BA {
!endif
!endif
+!if $(ESRT_ENABLE) == TRUE
+ INF MdeModulePkg/Universal/EsrtDxe/EsrtDxe.inf
+ INF $(PLATFORM_PACKAGE)/PlatformEsrt/PlatformEsrtDxe.inf
+ INF $(PLATFORM_PACKAGE)/FmpSample/FmpSample.inf
+!endif
+
[FV.FVMAIN_COMPACT]
BlockSize = $(FLASH_BLOCK_SIZE)
FvAlignment = 16
@@ -739,7 +745,7 @@ READ_LOCK_CAP = TRUE
READ_LOCK_STATUS = TRUE
-[FV.Update_Data]
+[FV.Bios_Update_Data]
BlockSize = $(FLASH_BLOCK_SIZE)
FvAlignment = 16
ERASE_POLARITY = 1
@@ -758,8 +764,8 @@ READ_STATUS = TRUE
READ_LOCK_CAP = TRUE
READ_LOCK_STATUS = TRUE
-FILE RAW = 88888888-8888-8888-8888-888888888888 {
- FD = Vlv
+FILE FV_IMAGE = 4A538818-5AE0-4eb2-B2EB-488B23657022 {
+ SECTION FV_IMAGE = FVMAIN_COMPACT
}
[FV.BiosUpdateCargo]
@@ -781,6 +787,17 @@ READ_STATUS = TRUE
READ_LOCK_CAP = TRUE
READ_LOCK_STATUS = TRUE
+!if $(ESRT_ENABLE) == TRUE
+ INF $(PLATFORM_PACKAGE)/UpdateDriverDxe/UpdateDriverDxe.inf
+!else
+ INF IntelFrameworkModulePkg/Universal/FirmwareVolume/UpdateDriverDxe/UpdateDriverDxe.inf
+!endif
+FILE RAW = 283FA2EE-532C-484d-9383-9F93B36F0B7E {
+ FV = Bios_Update_Data
+ }
+FILE RAW = 98B8D59B-E8BA-48EE-98DD-C295392F1EDB {
+ Vlv2TbltDevicePkg/BiosUpdateConfig/BiosUpdateConfig.ini
+ }
[FV.BiosUpdate]
@@ -802,23 +819,33 @@ READ_STATUS = TRUE
READ_LOCK_CAP = TRUE
READ_LOCK_STATUS = TRUE
+FILE FV_IMAGE = EDBEDF47-6EA3-4512-83C1-70F4769D4BDE {
+ SECTION GUIDED {
+ SECTION FV_IMAGE = BiosUpdateCargo
+ }
+ }
+
[Capsule.Capsule_Boot]
-#
-# gEfiCapsuleGuid supported by platform
-# { 0x3B6686BD, 0x0D76, 0x4030, { 0xB7, 0x0E, 0xB5, 0x51, 0x9E, 0x2F, 0xC5, 0xA0 }}
-#
-CAPSULE_GUID = 3B6686BD-0D76-4030-B70E-B5519E2FC5A0
-CAPSULE_FLAGS = PersistAcrossReset
+!if $(ESRT_ENABLE) == TRUE
+CAPSULE_GUID = 819b858e-c52c-402f-80e1-5b311b6c1959
+!else
+CAPSULE_GUID = 3B6686BD-0D76-4030-B70E-B5519E2FC5A0
+!endif
+
+CAPSULE_FLAGS = PersistAcrossReset, InitiateReset
+OEM_CAPSULE_FLAGS = 0x0001
+
CAPSULE_HEADER_SIZE = 0x20
FV = BiosUpdate
[Capsule.Capsule_Reset]
-#
-# gEfiCapsuleGuid supported by platform
-# { 0x3B6686BD, 0x0D76, 0x4030, { 0xB7, 0x0E, 0xB5, 0x51, 0x9E, 0x2F, 0xC5, 0xA0 }}
-#
-CAPSULE_GUID = 3B6686BD-0D76-4030-B70E-B5519E2FC5A0
+!if $(ESRT_ENABLE) == TRUE
+CAPSULE_GUID = 819b858e-c52c-402f-80e1-5b311b6c1959
+!else
+CAPSULE_GUID = 3B6686BD-0D76-4030-B70E-B5519E2FC5A0
+!endif
+
CAPSULE_FLAGS = PersistAcrossReset
CAPSULE_HEADER_SIZE = 0x20
diff --git a/Vlv2TbltDevicePkg/PlatformPkgGccX64.dsc b/Vlv2TbltDevicePkg/PlatformPkgGccX64.dsc
index 3891c7752a..f7842af05e 100644
--- a/Vlv2TbltDevicePkg/PlatformPkgGccX64.dsc
+++ b/Vlv2TbltDevicePkg/PlatformPkgGccX64.dsc
@@ -181,11 +181,15 @@
!endif
OemHookStatusCodeLib|MdeModulePkg/Library/OemHookStatusCodeLibNull/OemHookStatusCodeLibNull.inf
-!if $(CAPSULE_ENABLE) == TRUE
- CapsuleLib|IntelFrameworkModulePkg/Library/DxeCapsuleLib/DxeCapsuleLib.inf
+
+!if $(ESRT_ENABLE) == TRUE
+ CapsuleLib|$(PLATFORM_PACKAGE)/Library/DxeEsrtCapsuleBsLib/DxeEsrtCapsuleBsLib.inf
!else
- CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf
+ CapsuleLib|IntelFrameworkModulePkg/Library/DxeCapsuleLib/DxeCapsuleLib.inf
!endif
+
+ UefiBootManagerLib|MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf
+
LanguageLib|EdkCompatibilityPkg/Compatibility/Library/UefiLanguageLib/UefiLanguageLib.inf
SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
SecurityManagementLib|MdeModulePkg/Library/DxeSecurityManagementLib/DxeSecurityManagementLib.inf
@@ -681,6 +685,9 @@
gEfiMdeModulePkgTokenSpaceGuid.PcdSerialUseHardwareFlowControl|FALSE
!endif
+[PcdsFixedAtBuild.X64]
+gEfiMdeModulePkgTokenSpaceGuid.PcdSystemRebootAfterCapsuleProcessFlag|0x0001
+
[PcdsFixedAtBuild.IA32.PEIM, PcdsFixedAtBuild.IA32.PEI_CORE, PcdsFixedAtBuild.IA32.SEC]
!if $(TARGET) == RELEASE
gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x0
@@ -823,6 +830,15 @@
gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut|L"Timeout"|gEfiGlobalVariableGuid|0x0|5 # Variable: L"Timeout"
gEfiMdePkgTokenSpaceGuid.PcdHardwareErrorRecordLevel|L"HwErrRecSupport"|gEfiGlobalVariableGuid|0x0|1 # Variable: L"HwErrRecSupport"
gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdBootState|L"BootState"|gEfiBootStateGuid|0x0|TRUE
+
+ #
+ # Indicator to sync ESRT repository from FMP instance. Set to TRUE on first boot
+ #
+!if $(ESRT_ENABLE) == TRUE
+ gPlatformModuleTokenSpaceGuid.PcdEsrtSyncFmp|L"EsrtSyncFmp"|gPlatformModuleTokenSpaceGuid|0x0|TRUE|NV,BS
+!else
+ gPlatformModuleTokenSpaceGuid.PcdEsrtSyncFmp|L"EsrtSyncFmp"|gPlatformModuleTokenSpaceGuid|0x0|FALSE|NV,BS
+!endif
[PcdsDynamicDefault.common.DEFAULT]
gEfiMdeModulePkgTokenSpaceGuid.PcdS3BootScriptTablePrivateDataPtr|0x0
@@ -1178,7 +1194,9 @@ $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/fTPMInitPeim.inf
!endif
MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf {
<LibraryClasses>
- FileHandleLib|MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.inf
+ !if $(ESRT_ENABLE) == TRUE
+ CapsuleLib|$(PLATFORM_PACKAGE)/Library/DxeEsrtCapsuleRtLib/DxeEsrtCapsuleRtLib.inf
+!endif
}
MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf
@@ -1512,6 +1530,28 @@ $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/fTPMInitPeim.inf
!endif
!endif
+#
+# capsule related drivers
+#
+IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/FwVolDxe.inf
+!if $(ESRT_ENABLE) == TRUE
+ $(PLATFORM_PACKAGE)/UpdateDriverDxe/UpdateDriverDxe.inf{
+ !if $(TARGET) == DEBUG
+ <LibraryClasses>
+ DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
+ SerialPortLib|$(PLATFORM_PACKAGE)/Library/SerialPortLib/SerialPortLib.inf
+ !endif
+ }
+!else
+ IntelFrameworkModulePkg/Universal/FirmwareVolume/UpdateDriverDxe/UpdateDriverDxe.inf
+!endif
+MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmmDxe.inf
+!if $(ESRT_ENABLE) == TRUE
+ MdeModulePkg/Universal/EsrtDxe/EsrtDxe.inf
+ $(PLATFORM_PACKAGE)/PlatformEsrt/PlatformEsrtDxe.inf
+ $(PLATFORM_PACKAGE)/FmpSample/FmpSample.inf
+!endif
+
Vlv2TbltDevicePkg/Application/FirmwareUpdate/FirmwareUpdate.inf
Vlv2TbltDevicePkg/Application/SsdtUpdate/SsdtUpdate.inf
diff --git a/Vlv2TbltDevicePkg/PlatformPkgIA32.dsc b/Vlv2TbltDevicePkg/PlatformPkgIA32.dsc
index 684f2fe1ef..61e28318b3 100644
--- a/Vlv2TbltDevicePkg/PlatformPkgIA32.dsc
+++ b/Vlv2TbltDevicePkg/PlatformPkgIA32.dsc
@@ -181,11 +181,15 @@
!endif
OemHookStatusCodeLib|MdeModulePkg/Library/OemHookStatusCodeLibNull/OemHookStatusCodeLibNull.inf
-!if $(CAPSULE_ENABLE) == TRUE
- CapsuleLib|IntelFrameworkModulePkg/Library/DxeCapsuleLib/DxeCapsuleLib.inf
+
+!if $(ESRT_ENABLE) == TRUE
+ CapsuleLib|$(PLATFORM_PACKAGE)/Library/DxeEsrtCapsuleBsLib/DxeEsrtCapsuleBsLib.inf
!else
- CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf
+ CapsuleLib|IntelFrameworkModulePkg/Library/DxeCapsuleLib/DxeCapsuleLib.inf
!endif
+
+ UefiBootManagerLib|MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf
+
LanguageLib|EdkCompatibilityPkg/Compatibility/Library/UefiLanguageLib/UefiLanguageLib.inf
SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
SecurityManagementLib|MdeModulePkg/Library/DxeSecurityManagementLib/DxeSecurityManagementLib.inf
@@ -681,6 +685,9 @@
gEfiMdeModulePkgTokenSpaceGuid.PcdSerialUseHardwareFlowControl|FALSE
!endif
+[PcdsFixedAtBuild.X64]
+gEfiMdeModulePkgTokenSpaceGuid.PcdSystemRebootAfterCapsuleProcessFlag|0x0001
+
[PcdsFixedAtBuild.IA32.PEIM, PcdsFixedAtBuild.IA32.PEI_CORE, PcdsFixedAtBuild.IA32.SEC]
!if $(TARGET) == RELEASE
gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x0
@@ -823,6 +830,15 @@
gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut|L"Timeout"|gEfiGlobalVariableGuid|0x0|5 # Variable: L"Timeout"
gEfiMdePkgTokenSpaceGuid.PcdHardwareErrorRecordLevel|L"HwErrRecSupport"|gEfiGlobalVariableGuid|0x0|1 # Variable: L"HwErrRecSupport"
gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdBootState|L"BootState"|gEfiBootStateGuid|0x0|TRUE
+
+ #
+ # Indicator to sync ESRT repository from FMP instance. Set to TRUE on first boot
+ #
+!if $(ESRT_ENABLE) == TRUE
+ gPlatformModuleTokenSpaceGuid.PcdEsrtSyncFmp|L"EsrtSyncFmp"|gPlatformModuleTokenSpaceGuid|0x0|TRUE|NV,BS
+!else
+ gPlatformModuleTokenSpaceGuid.PcdEsrtSyncFmp|L"EsrtSyncFmp"|gPlatformModuleTokenSpaceGuid|0x0|FALSE|NV,BS
+!endif
[PcdsDynamicDefault.common.DEFAULT]
gEfiMdeModulePkgTokenSpaceGuid.PcdS3BootScriptTablePrivateDataPtr|0x0
@@ -1101,6 +1117,8 @@ $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/fTPMInitPeim.inf
!endif
}
+
+
MdeModulePkg/Universal/ReportStatusCodeRouter/Smm/ReportStatusCodeRouterSmm.inf
MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf{
<LibraryClasses>
@@ -1164,14 +1182,22 @@ $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/fTPMInitPeim.inf
!endif
MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf {
<LibraryClasses>
- FileHandleLib|MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.inf
+ !if $(ESRT_ENABLE) == TRUE
+ CapsuleLib|$(PLATFORM_PACKAGE)/Library/DxeEsrtCapsuleRtLib/DxeEsrtCapsuleRtLib.inf
+!endif
}
MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf
PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcatRealTimeClockRuntimeDxe.inf
MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf
- $(PLATFORM_PACKAGE)/FvbRuntimeDxe/FvbRuntimeDxe.inf
+ $(PLATFORM_PACKAGE)/FvbRuntimeDxe/FvbRuntimeDxe.inf {
+ !if $(TARGET) == DEBUG
+ <LibraryClasses>
+ DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
+ SerialPortLib|$(PLATFORM_PACKAGE)/Library/SerialPortLib/SerialPortLib.inf
+ !endif
+ }
$(PLATFORM_PACKAGE)/PlatformSetupDxe/PlatformSetupDxe.inf
@@ -1492,6 +1518,28 @@ $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/fTPMInitPeim.inf
!endif
!endif
+#
+# capsule related drivers
+#
+IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/FwVolDxe.inf
+!if $(ESRT_ENABLE) == TRUE
+ $(PLATFORM_PACKAGE)/UpdateDriverDxe/UpdateDriverDxe.inf{
+ !if $(TARGET) == DEBUG
+ <LibraryClasses>
+ DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
+ SerialPortLib|$(PLATFORM_PACKAGE)/Library/SerialPortLib/SerialPortLib.inf
+ !endif
+ }
+!else
+ IntelFrameworkModulePkg/Universal/FirmwareVolume/UpdateDriverDxe/UpdateDriverDxe.inf
+!endif
+MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmmDxe.inf
+!if $(ESRT_ENABLE) == TRUE
+ MdeModulePkg/Universal/EsrtDxe/EsrtDxe.inf
+ $(PLATFORM_PACKAGE)/PlatformEsrt/PlatformEsrtDxe.inf
+ $(PLATFORM_PACKAGE)/FmpSample/FmpSample.inf
+!endif
+
Vlv2TbltDevicePkg/Application/FirmwareUpdate/FirmwareUpdate.inf
Vlv2TbltDevicePkg/Application/SsdtUpdate/SsdtUpdate.inf
diff --git a/Vlv2TbltDevicePkg/PlatformPkgX64.dsc b/Vlv2TbltDevicePkg/PlatformPkgX64.dsc
index a07df1cb7e..c3e29b3f06 100644
--- a/Vlv2TbltDevicePkg/PlatformPkgX64.dsc
+++ b/Vlv2TbltDevicePkg/PlatformPkgX64.dsc
@@ -181,11 +181,15 @@
!endif
OemHookStatusCodeLib|MdeModulePkg/Library/OemHookStatusCodeLibNull/OemHookStatusCodeLibNull.inf
-!if $(CAPSULE_ENABLE) == TRUE
- CapsuleLib|IntelFrameworkModulePkg/Library/DxeCapsuleLib/DxeCapsuleLib.inf
+
+!if $(ESRT_ENABLE) == TRUE
+ CapsuleLib|$(PLATFORM_PACKAGE)/Library/DxeEsrtCapsuleBsLib/DxeEsrtCapsuleBsLib.inf
!else
- CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf
+ CapsuleLib|IntelFrameworkModulePkg/Library/DxeCapsuleLib/DxeCapsuleLib.inf
!endif
+
+ UefiBootManagerLib|MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf
+
LanguageLib|EdkCompatibilityPkg/Compatibility/Library/UefiLanguageLib/UefiLanguageLib.inf
SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
SecurityManagementLib|MdeModulePkg/Library/DxeSecurityManagementLib/DxeSecurityManagementLib.inf
@@ -681,6 +685,9 @@
gEfiMdeModulePkgTokenSpaceGuid.PcdSerialUseHardwareFlowControl|FALSE
!endif
+[PcdsFixedAtBuild.X64]
+gEfiMdeModulePkgTokenSpaceGuid.PcdSystemRebootAfterCapsuleProcessFlag|0x0001
+
[PcdsFixedAtBuild.IA32.PEIM, PcdsFixedAtBuild.IA32.PEI_CORE, PcdsFixedAtBuild.IA32.SEC]
!if $(TARGET) == RELEASE
gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x0
@@ -823,6 +830,15 @@
gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut|L"Timeout"|gEfiGlobalVariableGuid|0x0|5 # Variable: L"Timeout"
gEfiMdePkgTokenSpaceGuid.PcdHardwareErrorRecordLevel|L"HwErrRecSupport"|gEfiGlobalVariableGuid|0x0|1 # Variable: L"HwErrRecSupport"
gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdBootState|L"BootState"|gEfiBootStateGuid|0x0|TRUE
+
+ #
+ # Indicator to sync ESRT repository from FMP instance. Set to TRUE on first boot
+ #
+!if $(ESRT_ENABLE) == TRUE
+ gPlatformModuleTokenSpaceGuid.PcdEsrtSyncFmp|L"EsrtSyncFmp"|gPlatformModuleTokenSpaceGuid|0x0|TRUE|NV,BS
+!else
+ gPlatformModuleTokenSpaceGuid.PcdEsrtSyncFmp|L"EsrtSyncFmp"|gPlatformModuleTokenSpaceGuid|0x0|FALSE|NV,BS
+!endif
[PcdsDynamicDefault.common.DEFAULT]
gEfiMdeModulePkgTokenSpaceGuid.PcdS3BootScriptTablePrivateDataPtr|0x0
@@ -1174,6 +1190,9 @@ $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/fTPMInitPeim.inf
!endif
MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf {
<LibraryClasses>
+ !if $(ESRT_ENABLE) == TRUE
+ CapsuleLib|$(PLATFORM_PACKAGE)/Library/DxeEsrtCapsuleRtLib/DxeEsrtCapsuleRtLib.inf
+ !endif
FileHandleLib|MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.inf
}
@@ -1181,7 +1200,13 @@ $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/fTPMInitPeim.inf
PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcatRealTimeClockRuntimeDxe.inf
MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf
- $(PLATFORM_PACKAGE)/FvbRuntimeDxe/FvbRuntimeDxe.inf
+ $(PLATFORM_PACKAGE)/FvbRuntimeDxe/FvbRuntimeDxe.inf {
+ !if $(TARGET) == DEBUG
+ <LibraryClasses>
+ DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
+ SerialPortLib|$(PLATFORM_PACKAGE)/Library/SerialPortLib/SerialPortLib.inf
+ !endif
+ }
$(PLATFORM_PACKAGE)/PlatformSetupDxe/PlatformSetupDxe.inf
@@ -1502,6 +1527,28 @@ $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/fTPMInitPeim.inf
!endif
!endif
+#
+# capsule related drivers
+#
+IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/FwVolDxe.inf
+!if $(ESRT_ENABLE) == TRUE
+ $(PLATFORM_PACKAGE)/UpdateDriverDxe/UpdateDriverDxe.inf{
+ !if $(TARGET) == DEBUG
+ <LibraryClasses>
+ DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
+ SerialPortLib|$(PLATFORM_PACKAGE)/Library/SerialPortLib/SerialPortLib.inf
+ !endif
+ }
+!else
+ IntelFrameworkModulePkg/Universal/FirmwareVolume/UpdateDriverDxe/UpdateDriverDxe.inf
+!endif
+MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmmDxe.inf
+!if $(ESRT_ENABLE) == TRUE
+ MdeModulePkg/Universal/EsrtDxe/EsrtDxe.inf
+ $(PLATFORM_PACKAGE)/PlatformEsrt/PlatformEsrtDxe.inf
+ $(PLATFORM_PACKAGE)/FmpSample/FmpSample.inf
+!endif
+
Vlv2TbltDevicePkg/Application/FirmwareUpdate/FirmwareUpdate.inf
Vlv2TbltDevicePkg/Application/SsdtUpdate/SsdtUpdate.inf
diff --git a/Vlv2TbltDevicePkg/UpdateDriverDxe/FlashUpdate.c b/Vlv2TbltDevicePkg/UpdateDriverDxe/FlashUpdate.c
new file mode 100644
index 0000000000..95216c9d24
--- /dev/null
+++ b/Vlv2TbltDevicePkg/UpdateDriverDxe/FlashUpdate.c
@@ -0,0 +1,1217 @@
+/** @file
+ Functions in this file will program the image into flash area.
+
+ Copyright (c) 2004 - 2016, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ 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 "UpdateDriver.h"
+
+/**
+ Write a block size data into flash.
+
+ @param FvbProtocol Pointer to FVB protocol.
+ @param Lba Logic block index to be updated.
+ @param BlockSize Block size
+ @param Buffer Buffer data to be written.
+
+ @retval EFI_SUCCESS Write data successfully.
+ @retval other errors Write data failed.
+
+**/
+EFI_STATUS
+UpdateOneBlock (
+ IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvbProtocol,
+ IN EFI_LBA Lba,
+ IN UINTN BlockSize,
+ IN UINT8 *Buffer
+ )
+{
+ EFI_STATUS Status;
+ UINTN Size;
+
+ //
+ // First erase the block
+ //
+ Status = FvbProtocol->EraseBlocks (
+ FvbProtocol,
+ Lba, // Lba
+ 1, // NumOfBlocks
+ EFI_LBA_LIST_TERMINATOR
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Write the block
+ //
+ Size = BlockSize;
+ Status = FvbProtocol->Write (
+ FvbProtocol,
+ Lba, // Lba
+ 0, // Offset
+ &Size, // Size
+ Buffer // Buffer
+ );
+ if ((EFI_ERROR (Status)) || (Size != BlockSize)) {
+ return Status;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Write buffer data in a flash block.
+
+ @param FvbProtocol Pointer to FVB protocol.
+ @param Lba Logic block index to be updated.
+ @param Offset The offset within the block.
+ @param Length Size of buffer to be updated.
+ @param BlockSize Block size.
+ @param Buffer Buffer data to be updated.
+
+ @retval EFI_SUCCESS Write data successfully.
+ @retval other errors Write data failed.
+
+**/
+EFI_STATUS
+UpdateBufferInOneBlock (
+ IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvbProtocol,
+ IN EFI_LBA Lba,
+ IN UINTN Offset,
+ IN UINTN Length,
+ IN UINTN BlockSize,
+ IN UINT8 *Buffer
+ )
+{
+ EFI_STATUS Status;
+ UINTN Size;
+ UINT8 *ReservedBuffer;
+
+ //
+ // If we are going to update a whole block
+ //
+ if ((Offset == 0) && (Length == BlockSize)) {
+ Status = UpdateOneBlock (
+ FvbProtocol,
+ Lba,
+ BlockSize,
+ Buffer
+ );
+ return Status;
+ }
+
+ //
+ // If it is not a full block update, we need to coalesce data in
+ // the block that is not going to be updated and new data together.
+ //
+
+ //
+ // Allocate a reserved buffer to make up the final buffer for update
+ //
+ ReservedBuffer = NULL;
+ ReservedBuffer = AllocatePool (BlockSize);
+ if (ReservedBuffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // First get the original content of the block
+ //
+ Size = BlockSize;
+ Status = FvbProtocol->Read (
+ FvbProtocol,
+ Lba,
+ 0,
+ &Size,
+ ReservedBuffer
+ );
+ if ((EFI_ERROR (Status)) || (Size != BlockSize)) {
+ FreePool (ReservedBuffer);
+ return Status;
+ }
+
+ //
+ // Overwrite the reserved buffer with new content
+ //
+ CopyMem (ReservedBuffer + Offset, Buffer, Length);
+
+ Status = UpdateOneBlock (
+ FvbProtocol,
+ Lba,
+ BlockSize,
+ ReservedBuffer
+ );
+
+ FreePool (ReservedBuffer);
+
+ return Status;
+}
+
+/**
+ Get the last write log, and check the status of last write.
+ If not complete, restart will be taken.
+
+ @param FvbHandle Handle of FVB protocol.
+ @param FtwProtocol FTW protocol instance.
+ @param ConfigData Config data on updating driver.
+ @param PrivateDataSize bytes from the private data
+ stored for this write.
+ @param PrivateData A pointer to a buffer. The function will copy.
+ @param Lba The logical block address of the last write.
+ @param Offset The offset within the block of the last write.
+ @param Length The length of the last write.
+ @param Pending A Boolean value with TRUE indicating
+ that the write was completed.
+
+ @retval EFI_OUT_OF_RESOURCES No enough memory is allocated.
+ @retval EFI_ABORTED The FTW work space is damaged.
+ @retval EFI_NOT_FOUND The last write is not done by this driver.
+ @retval EFI_SUCCESS Last write log is got.
+
+**/
+EFI_STATUS
+RetrieveLastWrite (
+ IN EFI_HANDLE FvbHandle,
+ IN EFI_FAULT_TOLERANT_WRITE_PROTOCOL *FtwProtocol,
+ IN UPDATE_CONFIG_DATA *ConfigData,
+ IN UINTN PrivateDataSize,
+ IN OUT UPDATE_PRIVATE_DATA *PrivateData,
+ IN OUT EFI_LBA *Lba,
+ IN OUT UINTN *Offset,
+ IN OUT UINTN *Length,
+ IN OUT BOOLEAN *Pending
+ )
+{
+ EFI_STATUS Status;
+ EFI_GUID CallerId;
+ UINTN PrivateBufferSize;
+ BOOLEAN Complete;
+ VOID *PrivateDataBuffer;
+
+ //
+ // Get the last write
+ //
+ *Pending = FALSE;
+ PrivateBufferSize = PrivateDataSize;
+ PrivateDataBuffer = NULL;
+ Status = FtwProtocol->GetLastWrite (
+ FtwProtocol,
+ &CallerId,
+ Lba,
+ Offset,
+ Length,
+ &PrivateBufferSize,
+ PrivateData,
+ &Complete
+ );
+ if (EFI_ERROR (Status)) {
+ //
+ // If there is no incompleted record, return success.
+ //
+ if ((Status == EFI_NOT_FOUND) && Complete) {
+ return EFI_SUCCESS;
+ } else if (Status == EFI_BUFFER_TOO_SMALL) {
+ //
+ // If buffer too small, reallocate buffer and call getlastwrite again
+ //
+ PrivateDataBuffer = AllocatePool (PrivateBufferSize);
+
+ if (PrivateDataBuffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Status = FtwProtocol->GetLastWrite (
+ FtwProtocol,
+ &CallerId,
+ Lba,
+ Offset,
+ Length,
+ &PrivateBufferSize,
+ PrivateDataBuffer,
+ &Complete
+ );
+ if (EFI_ERROR (Status)) {
+ FreePool ( PrivateDataBuffer);
+ return EFI_ABORTED;
+ } else {
+ CopyMem (PrivateData, PrivateDataBuffer, PrivateDataSize);
+ FreePool (PrivateDataBuffer);
+ PrivateDataBuffer = NULL;
+ }
+ } else {
+ return EFI_ABORTED;
+ }
+ }
+
+ *Pending = TRUE;
+
+ //
+ // If the caller is not the update driver, then return.
+ // The update driver cannot continue to perform the update
+ //
+ if (CompareMem (&CallerId, &gEfiCallerIdGuid, sizeof (EFI_GUID)) != 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Check the private data and see if it is the one I need.
+ //
+ if (CompareMem (&(PrivateData->FileGuid), &(ConfigData->FileGuid), sizeof(EFI_GUID)) != 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // If the caller is the update driver and complete is not true, then restart().
+ //
+ if (!Complete) {
+ //
+ // Re-start the update
+ //
+ Status = FtwProtocol->Restart (
+ FtwProtocol,
+ FvbHandle
+ );
+ //
+ // If restart() error, then abort().
+ //
+ if (EFI_ERROR (Status)) {
+ FtwProtocol->Abort (FtwProtocol);
+ //
+ // Now set Pending as FALSE as this record has been cleared
+ //
+ *Pending = FALSE;
+ return EFI_SUCCESS;
+ }
+
+ }
+
+ return Status;
+}
+
+/**
+ Update the whole FV image in fault tolerant write method.
+
+ @param FvbHandle Handle of FVB protocol for the updated flash range.
+ @param FvbProtocol FVB protocol.
+ @param BlockMap Block array to specify flash area.
+ @param ConfigData Config data on updating driver.
+ @param ImageBuffer Image buffer to be updated.
+ @param ImageSize Image size.
+
+ @retval EFI_SUCCESS FV image is writed into flash.
+ @retval EFI_INVALID_PARAMETER Config data is not valid.
+ @retval EFI_NOT_FOUND FTW protocol doesn't exist.
+ @retval EFI_OUT_OF_RESOURCES No enough backup space.
+ @retval EFI_ABORTED Error happen when update FV.
+
+**/
+EFI_STATUS
+FaultTolerantUpdateOnWholeFv (
+ IN EFI_HANDLE FvbHandle,
+ IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvbProtocol,
+ IN EFI_FV_BLOCK_MAP_ENTRY *BlockMap,
+ IN UPDATE_CONFIG_DATA *ConfigData,
+ IN UINT8 *ImageBuffer,
+ IN UINTN ImageSize
+ )
+{
+ EFI_STATUS Status;
+ EFI_FAULT_TOLERANT_WRITE_PROTOCOL *FtwProtocol;
+ UINTN MaxBlockSize;
+ UINTN FtwMaxBlockSize;
+ BOOLEAN Pending;
+ UPDATE_PRIVATE_DATA PrivateData;
+ EFI_LBA PendingLba;
+ EFI_LBA Lba;
+ UINTN PendingOffset;
+ UINTN Offset;
+ UINTN PendingLength;
+ UINTN Length;
+ EFI_FV_BLOCK_MAP_ENTRY *PtrMap;
+ UINTN NumOfBlocks;
+ UINTN Index;
+ UINT8 *UpdateBuffer;
+
+ if ((ConfigData->UpdateType != UpdateWholeFV)
+ || (!ConfigData->FaultTolerant)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Get the FTW protocol
+ //
+ Status = gBS->LocateProtocol (
+ &gEfiFaultTolerantWriteProtocolGuid,
+ NULL,
+ (VOID **) &FtwProtocol
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Get the maximum block size of the FV, and number of blocks
+ // NumOfBlocks will be the NumOfUdpates.
+ //
+ MaxBlockSize = 0;
+ NumOfBlocks = 0;
+ PtrMap = BlockMap;
+ while (TRUE) {
+ if ((PtrMap->NumBlocks == 0) || (PtrMap->Length == 0)) {
+ break;
+ }
+ if (MaxBlockSize < PtrMap->Length) {
+ MaxBlockSize = PtrMap->Length;
+ }
+ NumOfBlocks = NumOfBlocks + PtrMap->NumBlocks;
+ PtrMap++;
+ }
+
+ FtwProtocol->GetMaxBlockSize (FtwProtocol, &FtwMaxBlockSize);
+ //
+ // Not enough backup space. return directly
+ //
+ if (FtwMaxBlockSize < MaxBlockSize) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ PendingLba = 0;
+ PendingOffset = 0;
+ PendingLength = 0;
+ Pending = FALSE;
+
+ //
+ // Fault Tolerant Write can only support actual fault tolerance if the write
+ // is a reclaim operation, which means the data buffer (new and old) are
+ // acutally both stored in flash. But for component update write, the data
+ // are now in memory. So we cannot actually recover the data after power
+ // failure.
+ //
+ Status = RetrieveLastWrite (
+ FvbHandle,
+ FtwProtocol,
+ ConfigData,
+ sizeof (UPDATE_PRIVATE_DATA),
+ &PrivateData,
+ &PendingLba,
+ &PendingOffset,
+ &PendingLength,
+ &Pending
+ );
+
+ if (Pending && (Status == EFI_NOT_FOUND)) {
+ //
+ // Cannot continue with the write operation
+ //
+ return EFI_ABORTED;
+ }
+
+ if (EFI_ERROR(Status)) {
+ return EFI_ABORTED;
+ }
+
+ //
+ // Currently we start from the pending write if there is any. But as we
+ // are going to update a whole FV, we can just abort last write and start
+ // from the very begining.
+ //
+ if (!Pending) {
+ //
+ // Now allocte the update private data in FTW. If there is pending
+ // write, it has already been allocated and no need to allocate here.
+ //
+ Status = FtwProtocol->Allocate (
+ FtwProtocol,
+ &gEfiCallerIdGuid,
+ sizeof (UPDATE_PRIVATE_DATA),
+ NumOfBlocks
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ //
+ // Perform the update now. If there are pending writes, we need to
+ // start from the pending write instead of the very beginning.
+ //
+ PtrMap = BlockMap;
+ Lba = 0;
+ Offset = 0;
+ UpdateBuffer = ImageBuffer;
+ CopyMem (
+ (VOID *) &PrivateData.FileGuid,
+ (VOID *) &ConfigData->FileGuid,
+ sizeof (EFI_GUID)
+ );
+
+ while (TRUE) {
+ if ((PtrMap->NumBlocks == 0) || (PtrMap->Length == 0)) {
+ break;
+ }
+ Length = (UINTN)PtrMap->Length;
+ for (Index = 0; Index < PtrMap->NumBlocks; Index++) {
+
+ //
+ // Add an extra check here to see if the pending record is correct
+ //
+ if (Pending && (Lba == PendingLba)) {
+ if ((PendingOffset != Offset) || (PendingLength != Length)) {
+ //
+ // Error.
+ //
+ Status = EFI_ABORTED;
+ break;
+ }
+ }
+
+ if ((!Pending) || (Lba >= PendingLba)) {
+ Status = FtwProtocol->Write (
+ FtwProtocol,
+ Lba, // Lba
+ Offset, // Offset
+ Length, // Size
+ &PrivateData, // Private Data
+ FvbHandle, // FVB handle
+ UpdateBuffer // Buffer
+ );
+ }
+
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+ Lba++;
+ UpdateBuffer = (UINT8 *) ((UINTN)UpdateBuffer + Length);
+ }
+
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+ PtrMap++;
+ }
+
+ return Status;
+
+}
+
+/**
+ Directly update the whole FV image without fault tolerant write method.
+
+ @param FvbHandle Handle of FVB protocol for the updated flash range.
+ @param FvbProtocol FVB protocol.
+ @param BlockMap Block array to specify flash area.
+ @param ConfigData Config data on updating driver.
+ @param ImageBuffer Image buffer to be updated.
+ @param ImageSize Image size.
+
+ @retval EFI_SUCCESS FV image is writed into flash.
+ @retval EFI_INVALID_PARAMETER Config data is not valid.
+ @retval EFI_ABORTED Error happen when update FV.
+
+**/
+EFI_STATUS
+NonFaultTolerantUpdateOnWholeFv (
+ IN EFI_HANDLE FvbHandle,
+ IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvbProtocol,
+ IN EFI_FV_BLOCK_MAP_ENTRY *BlockMap,
+ IN UPDATE_CONFIG_DATA *ConfigData,
+ IN UINT8 *ImageBuffer,
+ IN UINTN ImageSize
+ )
+{
+ EFI_STATUS Status;
+ EFI_FV_BLOCK_MAP_ENTRY *PtrMap;
+ UINTN Index;
+ EFI_LBA UpdateLba;
+ UINT8 *UpdateBuffer;
+ UINTN UpdateSize;
+
+ if ((ConfigData->UpdateType != UpdateWholeFV )
+ || (ConfigData->FaultTolerant)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = EFI_SUCCESS;
+ PtrMap = BlockMap;
+ UpdateLba = 0;
+ UpdateBuffer = ImageBuffer;
+
+ //
+ // Perform the update now
+ //
+ while (TRUE) {
+ if ((PtrMap->NumBlocks == 0) || (PtrMap->Length == 0)) {
+ break;
+ }
+ UpdateSize = (UINTN)PtrMap->Length;
+ for (Index = 0; Index < PtrMap->NumBlocks; Index++) {
+ Status = UpdateOneBlock (
+ FvbProtocol,
+ UpdateLba,
+ UpdateSize,
+ UpdateBuffer
+ );
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+
+ UpdateLba++;
+ UpdateBuffer = (UINT8 *) ((UINTN)UpdateBuffer + UpdateSize);
+ }
+
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+ PtrMap++;
+ }
+
+ return Status;
+}
+
+/**
+ Update the whole FV image, and reinsall FVB protocol for the updated FV image.
+
+ @param FvbHandle Handle of FVB protocol for the updated flash range.
+ @param FvbProtocol FVB protocol.
+ @param ConfigData Config data on updating driver.
+ @param ImageBuffer Image buffer to be updated.
+ @param ImageSize Image size.
+
+ @retval EFI_INVALID_PARAMETER Update type is not UpdateWholeFV.
+ Or Image size is not same to the size of whole FV.
+ @retval EFI_OUT_OF_RESOURCES No enoug memory is allocated.
+ @retval EFI_SUCCESS FV image is updated, and its FVB protocol is reinstalled.
+
+**/
+EFI_STATUS
+PerformUpdateOnWholeFv (
+ IN EFI_HANDLE FvbHandle,
+ IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvbProtocol,
+ IN UPDATE_CONFIG_DATA *ConfigData,
+ IN UINT8 *ImageBuffer,
+ IN UINTN ImageSize
+)
+{
+ EFI_STATUS Status;
+ EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
+ EFI_FV_BLOCK_MAP_ENTRY *BlockMap;
+ CHAR16 *TmpStr;
+
+ if (ConfigData->UpdateType != UpdateWholeFV) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Get the header of the firmware volume
+ //
+ FwVolHeader = NULL;
+ FwVolHeader = AllocatePool (((EFI_FIRMWARE_VOLUME_HEADER *) ((UINTN) (ConfigData->BaseAddress)))->HeaderLength);
+ if (FwVolHeader == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ CopyMem (
+ FwVolHeader,
+ (VOID *) ((UINTN) (ConfigData->BaseAddress)),
+ ((EFI_FIRMWARE_VOLUME_HEADER *) ((UINTN) (ConfigData->BaseAddress)))->HeaderLength
+ );
+
+ //
+ // Check if ImageSize is the same as the size of the whole FV
+ //
+ if ((UINT64)ImageSize != FwVolHeader->FvLength) {
+ FreePool (FwVolHeader);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Print on screen
+ //
+ TmpStr = HiiGetString (gHiiHandle, STRING_TOKEN(UPDATE_FIRMWARE_VOLUME), NULL);
+ if (TmpStr != NULL) {
+ Print (TmpStr, ConfigData->BaseAddress, (FwVolHeader->FvLength + ConfigData->BaseAddress));
+ FreePool (TmpStr);
+ }
+
+ DEBUG ((EFI_D_UPDATE, "UpdateDriver: updating whole FV from %08LX to %08LX\n",
+ ConfigData->BaseAddress, (FwVolHeader->FvLength + ConfigData->BaseAddress)));
+
+ //
+ // Get the block map of the firmware volume
+ //
+ BlockMap = &(FwVolHeader->BlockMap[0]);
+
+ //
+ // It is about the same if we are going to fault tolerantly update
+ // a certain FV in our current design. But we divide non-fault tolerant
+ // and fault tolerant udpate here for better maintenance as fault
+ // tolerance may change and may be done more wisely if we have space.
+ //
+ if (ConfigData->FaultTolerant) {
+ Status = FaultTolerantUpdateOnWholeFv (
+ FvbHandle,
+ FvbProtocol,
+ BlockMap,
+ ConfigData,
+ ImageBuffer,
+ ImageSize
+ );
+ } else {
+ Status = NonFaultTolerantUpdateOnWholeFv (
+ FvbHandle,
+ FvbProtocol,
+ BlockMap,
+ ConfigData,
+ ImageBuffer,
+ ImageSize
+ );
+ }
+
+ FreePool (FwVolHeader);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // As the whole FV has been replaced, the FV driver shall re-parse the
+ // firmware volume. So re-install FVB protocol here
+ //
+ Status = gBS->ReinstallProtocolInterface (
+ FvbHandle,
+ &gEfiFirmwareVolumeBlockProtocolGuid,
+ FvbProtocol,
+ FvbProtocol
+ );
+
+ return Status;
+}
+
+/**
+ Update certain file in the FV.
+
+ @param FvbHandle Handle of FVB protocol for the updated flash range.
+ @param FvbProtocol FVB protocol.
+ @param ConfigData Config data on updating driver.
+ @param ImageBuffer Image buffer to be updated.
+ @param ImageSize Image size.
+ @param FileType FFS file type.
+ @param FileAttributes FFS file attribute
+
+ @retval EFI_INVALID_PARAMETER Update type is not UpdateFvFile.
+ Or Image size is not same to the size of whole FV.
+ @retval EFI_UNSUPPORTED PEIM FFS is unsupported to be updated.
+ @retval EFI_SUCCESS The FFS file is added into FV.
+
+**/
+EFI_STATUS
+PerformUpdateOnFvFile (
+ IN EFI_HANDLE FvbHandle,
+ IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvbProtocol,
+ IN UPDATE_CONFIG_DATA *ConfigData,
+ IN UINT8 *ImageBuffer,
+ IN UINTN ImageSize,
+ IN EFI_FV_FILETYPE FileType,
+ IN EFI_FV_FILE_ATTRIBUTES FileAttributes
+ )
+{
+ EFI_STATUS Status;
+ EFI_FIRMWARE_VOLUME2_PROTOCOL *FwVolProtocol;
+ EFI_FV_WRITE_FILE_DATA FileData;
+ CHAR16 *TmpStr;
+
+ if (ConfigData->UpdateType != UpdateFvFile) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Print on screen
+ //
+ TmpStr = HiiGetString (gHiiHandle, STRING_TOKEN(UPDATE_FIRMWARE_VOLUME_FILE), NULL);
+ if (TmpStr != NULL) {
+ Print (TmpStr, &(ConfigData->FileGuid));
+ FreePool (TmpStr);
+ }
+
+ DEBUG ((EFI_D_UPDATE, "UpdateDriver: updating file: %g\n",
+ &(ConfigData->FileGuid)));
+
+ //
+ // Get Firmware volume protocol on this FVB protocol
+ //
+ Status = gBS->HandleProtocol (
+ FvbHandle,
+ &gEfiFirmwareVolume2ProtocolGuid,
+ (VOID **) &FwVolProtocol
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // If it is a PEIM, we need first to rebase it before committing
+ // the write to target
+ //
+ if ((FileType == EFI_FV_FILETYPE_PEI_CORE) || (FileType == EFI_FV_FILETYPE_PEIM )
+ || (FileType == EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ FileData.NameGuid = &(ConfigData->FileGuid);
+ FileData.Type = FileType;
+ FileData.FileAttributes = FileAttributes;
+ FileData.Buffer = ImageBuffer;
+ FileData.BufferSize = (UINT32) ImageSize;
+
+ Status = FwVolProtocol->WriteFile (
+ FwVolProtocol,
+ 1, // NumberOfFiles
+ (EFI_FV_WRITE_POLICY)ConfigData->FaultTolerant,
+ &FileData
+ );
+ return Status;
+}
+
+/**
+ Update the buffer into flash area in fault tolerant write method.
+
+ @param ImageBuffer Image buffer to be updated.
+ @param SizeLeft Size of the image buffer.
+ @param UpdatedSize Size of the updated buffer.
+ @param ConfigData Config data on updating driver.
+ @param FlashAddress Flash address to be updated as start address.
+ @param FvbProtocol FVB protocol.
+ @param FvbHandle Handle of FVB protocol for the updated flash range.
+
+ @retval EFI_SUCCESS Buffer data is updated into flash.
+ @retval EFI_INVALID_PARAMETER Base flash address is not in FVB flash area.
+ @retval EFI_NOT_FOUND FTW protocol doesn't exist.
+ @retval EFI_OUT_OF_RESOURCES No enough backup space.
+ @retval EFI_ABORTED Error happen when update flash area.
+
+**/
+EFI_STATUS
+FaultTolerantUpdateOnPartFv (
+ IN UINT8 *ImageBuffer,
+ IN UINTN SizeLeft,
+ IN OUT UINTN *UpdatedSize,
+ IN UPDATE_CONFIG_DATA *ConfigData,
+ IN EFI_PHYSICAL_ADDRESS FlashAddress,
+ IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvbProtocol,
+ IN EFI_HANDLE FvbHandle
+ )
+{
+ EFI_STATUS Status;
+ EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
+ EFI_FIRMWARE_VOLUME_HEADER *FwVolHeaderTmp;
+ EFI_PHYSICAL_ADDRESS BaseAddress;
+ EFI_PHYSICAL_ADDRESS FvBase;
+ EFI_PHYSICAL_ADDRESS NextBlock;
+ EFI_FV_BLOCK_MAP_ENTRY *BlockMap;
+ EFI_FV_BLOCK_MAP_ENTRY *PtrMap;
+ UINTN NumOfUpdates;
+ UINTN TotalSize;
+ EFI_PHYSICAL_ADDRESS StartAddress;
+ EFI_FAULT_TOLERANT_WRITE_PROTOCOL *FtwProtocol;
+ UINTN MaxBlockSize;
+ UINTN FtwMaxBlockSize;
+ BOOLEAN Pending;
+ UPDATE_PRIVATE_DATA PrivateData;
+ EFI_LBA PendingLba;
+ EFI_LBA Lba;
+ UINTN BlockSize;
+ UINTN PendingOffset;
+ UINTN Offset;
+ UINTN PendingLength;
+ UINTN Length;
+ UINTN Index;
+ UINT8 *Image;
+
+ //
+ // Get the block map to update the block one by one
+ //
+ Status = FvbProtocol->GetPhysicalAddress (
+ FvbProtocol,
+ &FvBase
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ FwVolHeaderTmp = (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)FvBase;
+ if ((FlashAddress < FvBase) || (FlashAddress > (FvBase + FwVolHeaderTmp->FvLength))) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)AllocateCopyPool (
+ FwVolHeaderTmp->HeaderLength,
+ FwVolHeaderTmp
+ );
+ if (FwVolHeader == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // For fault tolerant write, we have to know how many blocks we need to
+ // update. So we will calculate number of updates and max block size first
+ //
+ NumOfUpdates = 0;
+ MaxBlockSize = 0;
+ TotalSize = SizeLeft;
+ StartAddress = FlashAddress;
+ BaseAddress = FvBase;
+ BlockMap = &(FwVolHeader->BlockMap[0]);
+ PtrMap = BlockMap;
+
+ while (TotalSize > 0) {
+ if ((PtrMap->NumBlocks == 0) || (PtrMap->Length == 0)) {
+ break;
+ }
+
+ BlockSize = PtrMap->Length;
+ for (Index = 0; Index < PtrMap->NumBlocks; Index++) {
+ NextBlock = BaseAddress + BlockSize;
+ //
+ // Check if this block need to be updated
+ //
+ if ((StartAddress >= BaseAddress) && (StartAddress < NextBlock)) {
+ //
+ // Get the maximum block size
+ //
+ if (MaxBlockSize < BlockSize) {
+ MaxBlockSize = BlockSize;
+ }
+
+ //
+ // This block shall be udpated. So increment number of updates
+ //
+ NumOfUpdates++;
+ Offset = (UINTN) (StartAddress - BaseAddress);
+ Length = TotalSize;
+ if ((Length + Offset ) > BlockSize) {
+ Length = BlockSize - Offset;
+ }
+
+ StartAddress = StartAddress + Length;
+ TotalSize = TotalSize - Length;
+ if (TotalSize <= 0) {
+ break;
+ }
+ }
+ BaseAddress = NextBlock;
+ }
+ PtrMap++;
+ }
+
+ //
+ // Get the FTW protocol
+ //
+ Status = gBS->LocateProtocol (
+ &gEfiFaultTolerantWriteProtocolGuid,
+ NULL,
+ (VOID **) &FtwProtocol
+ );
+ if (EFI_ERROR (Status)) {
+ FreePool (FwVolHeader);
+ return EFI_NOT_FOUND;
+ }
+
+ FtwProtocol->GetMaxBlockSize (FtwProtocol, &FtwMaxBlockSize);
+
+ //
+ // Not enough backup space. return directly
+ //
+ if (FtwMaxBlockSize < MaxBlockSize) {
+ FreePool (FwVolHeader);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ PendingLba = 0;
+ PendingOffset = 0;
+ PendingLength = 0;
+ Pending = FALSE;
+
+ //
+ // Fault Tolerant Write can only support actual fault tolerance if the write
+ // is a reclaim operation, which means the data buffer (new and old) are
+ // acutally both stored in flash. But for component update write, the data
+ // are now in memory. So we cannot actually recover the data after power
+ // failure.
+ //
+ Status = RetrieveLastWrite (
+ FvbHandle,
+ FtwProtocol,
+ ConfigData,
+ sizeof (UPDATE_PRIVATE_DATA),
+ &PrivateData,
+ &PendingLba,
+ &PendingOffset,
+ &PendingLength,
+ &Pending
+ );
+ if (Pending && (Status == EFI_NOT_FOUND)) {
+ //
+ // I'm not the owner of the pending fault tolerant write record
+ // Cannot continue with the write operation
+ //
+ FreePool (FwVolHeader);
+ return EFI_ABORTED;
+ }
+
+ if (EFI_ERROR(Status)) {
+ FreePool (FwVolHeader);
+ return EFI_ABORTED;
+ }
+
+ //
+ // Currently we start from the pending write if there is any. But if the
+ // caller is exactly the same, and the new data is already a in memory, (it
+ // cannot be stored in flash in last write,) we can just abort last write
+ // and start from the very begining.
+ //
+ if (!Pending) {
+ //
+ // Now allocte the update private data in FTW. If there is pending
+ // write, it has already been allocated and no need to allocate here.
+ //
+ Status = FtwProtocol->Allocate (
+ FtwProtocol,
+ &gEfiCallerIdGuid,
+ sizeof (UPDATE_PRIVATE_DATA),
+ NumOfUpdates
+ );
+ if (EFI_ERROR (Status)) {
+ FreePool (FwVolHeader);
+ return Status;
+ }
+ }
+
+ //
+ // Perform the update now. If there are pending writes, we need to
+ // start from the pending write instead of the very beginning.
+ //
+ TotalSize = SizeLeft;
+ Lba = 0;
+ StartAddress = FlashAddress;
+ BaseAddress = FvBase;
+ PtrMap = BlockMap;
+ Image = ImageBuffer;
+ CopyMem (
+ (VOID *) &PrivateData.FileGuid,
+ (VOID *) &ConfigData->FileGuid,
+ sizeof (EFI_GUID)
+ );
+
+ while (TotalSize > 0) {
+ if ((PtrMap->NumBlocks == 0) || (PtrMap->Length == 0)) {
+ break;
+ }
+
+ BlockSize = (UINTN)PtrMap->Length;
+ for (Index = 0; Index < PtrMap->NumBlocks; Index++) {
+ NextBlock = BaseAddress + BlockSize;
+ if ((StartAddress >= BaseAddress) && (StartAddress < NextBlock)) {
+ //
+ // So we need to update this block
+ //
+ Offset = (UINTN) (StartAddress - BaseAddress);
+ Length = TotalSize;
+ if ((Length + Offset ) > BlockSize) {
+ Length = BlockSize - Offset;
+ }
+
+ //
+ // Add an extra check here to see if the pending record is correct
+ //
+ if (Pending && (Lba == PendingLba)) {
+ if ((PendingOffset != Offset) || (PendingLength != Length)) {
+ //
+ // Error.
+ //
+ Status = EFI_ABORTED;
+ break;
+ }
+ }
+
+ if ((!Pending) || (Lba >= PendingLba)) {
+ DEBUG ((EFI_D_UPDATE, "Update Flash area from %08LX to %08LX\n", StartAddress, (UINT64)StartAddress + Length));
+ Status = FtwProtocol->Write (
+ FtwProtocol,
+ Lba, // Lba
+ Offset, // Offset
+ Length, // Size
+ &PrivateData, // Private Data
+ FvbHandle, // FVB handle
+ Image // Buffer
+ );
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+ }
+
+ //
+ // Now increment StartAddress, ImageBuffer and decrease the
+ // left size to prepare for the next block update.
+ //
+ StartAddress = StartAddress + Length;
+ Image = Image + Length;
+ TotalSize = TotalSize - Length;
+ if (TotalSize <= 0) {
+ break;
+ }
+ }
+ BaseAddress = NextBlock;
+ Lba++;
+ }
+
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+ PtrMap++;
+ }
+
+ FreePool (FwVolHeader);
+
+ *UpdatedSize = SizeLeft - TotalSize;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Directly update the buffer into flash area without fault tolerant write method.
+
+ @param ImageBuffer Image buffer to be updated.
+ @param SizeLeft Size of the image buffer.
+ @param UpdatedSize Size of the updated buffer.
+ @param FlashAddress Flash address to be updated as start address.
+ @param FvbProtocol FVB protocol.
+ @param FvbHandle Handle of FVB protocol for the updated flash range.
+
+ @retval EFI_SUCCESS Buffer data is updated into flash.
+ @retval EFI_INVALID_PARAMETER Base flash address is not in FVB flash area.
+ @retval EFI_OUT_OF_RESOURCES No enough backup space.
+
+**/
+EFI_STATUS
+NonFaultTolerantUpdateOnPartFv (
+ IN UINT8 *ImageBuffer,
+ IN UINTN SizeLeft,
+ IN OUT UINTN *UpdatedSize,
+ IN EFI_PHYSICAL_ADDRESS FlashAddress,
+ IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvbProtocol,
+ IN EFI_HANDLE FvbHandle
+ )
+{
+ EFI_STATUS Status;
+ EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
+ EFI_FIRMWARE_VOLUME_HEADER *FwVolHeaderTmp;
+ EFI_PHYSICAL_ADDRESS BaseAddress;
+ EFI_PHYSICAL_ADDRESS NextBlock;
+ EFI_FV_BLOCK_MAP_ENTRY *BlockMap;
+ UINTN Index;
+ UINTN TotalSize;
+ UINTN BlockSize;
+ EFI_LBA Lba;
+ UINTN Offset;
+ UINTN Length;
+ UINT8 *Image;
+
+ //
+ // Get the block map to update the block one by one
+ //
+ Status = FvbProtocol->GetPhysicalAddress (
+ FvbProtocol,
+ &BaseAddress
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ FwVolHeaderTmp = (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)BaseAddress;
+ if ((FlashAddress < BaseAddress) || (FlashAddress > ( BaseAddress + FwVolHeaderTmp->FvLength ))) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)AllocateCopyPool (
+ FwVolHeaderTmp->HeaderLength,
+ FwVolHeaderTmp
+ );
+ if (FwVolHeader == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Image = ImageBuffer;
+ TotalSize = SizeLeft;
+ BlockMap = &(FwVolHeader->BlockMap[0]);
+ Lba = 0;
+
+ while (TotalSize > 0) {
+ if ((BlockMap->NumBlocks == 0) || (BlockMap->Length == 0)) {
+ break;
+ }
+
+ BlockSize = BlockMap->Length;
+ for (Index = 0 ; Index < BlockMap->NumBlocks ; Index++) {
+ NextBlock = BaseAddress + BlockSize;
+ if ((FlashAddress >= BaseAddress) && (FlashAddress < NextBlock)) {
+ //
+ // So we need to update this block
+ //
+ Offset = (UINTN) FlashAddress - (UINTN) BaseAddress;
+ Length = TotalSize;
+ if ((Length + Offset ) > BlockSize) {
+ Length = BlockSize - Offset;
+ }
+
+ DEBUG ((EFI_D_UPDATE, "Update Flash area from %08LX to %08LX\n", FlashAddress, (UINT64)FlashAddress + Length));
+ //
+ // Update the block
+ //
+ Status = UpdateBufferInOneBlock (
+ FvbProtocol,
+ Lba,
+ Offset,
+ Length,
+ BlockSize,
+ Image
+ );
+ if (EFI_ERROR (Status)) {
+ FreePool (FwVolHeader);
+ return Status;
+ }
+
+ //
+ // Now increment FlashAddress, ImageBuffer and decrease the
+ // left size to prepare for the next block update.
+ //
+ FlashAddress = FlashAddress + Length;
+ Image = Image + Length;
+ TotalSize = TotalSize - Length;
+ if (TotalSize <= 0) {
+ break;
+ }
+ }
+ BaseAddress = NextBlock;
+ Lba++;
+ }
+
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+ BlockMap++;
+ }
+
+ FreePool (FwVolHeader);
+
+ *UpdatedSize = SizeLeft - TotalSize;
+
+ return EFI_SUCCESS;
+}
diff --git a/Vlv2TbltDevicePkg/UpdateDriverDxe/ParseUpdateProfile.c b/Vlv2TbltDevicePkg/UpdateDriverDxe/ParseUpdateProfile.c
new file mode 100644
index 0000000000..503d055598
--- /dev/null
+++ b/Vlv2TbltDevicePkg/UpdateDriverDxe/ParseUpdateProfile.c
@@ -0,0 +1,1134 @@
+/** @file
+ Source file for the component update driver. It parse the update
+ configuration file and pass the information to the update driver
+ so that the driver can perform updates accordingly.
+
+ Copyright (c) 2004 - 2016, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ 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 "UpdateDriver.h"
+
+/**
+ Copy one line data from buffer data to the line buffer.
+
+ @param Buffer Buffer data.
+ @param BufferSize Buffer Size.
+ @param LineBuffer Line buffer to store the found line data.
+ @param LineSize On input, size of the input line buffer.
+ On output, size of the actual line buffer.
+
+ @retval EFI_BUFFER_TOO_SMALL The size of input line buffer is not enough.
+ @retval EFI_SUCCESS Copy line data into the line buffer.
+
+**/
+EFI_STATUS
+ProfileGetLine (
+ IN UINT8 *Buffer,
+ IN UINTN BufferSize,
+ IN OUT UINT8 *LineBuffer,
+ IN OUT UINTN *LineSize
+ )
+{
+ UINTN Length;
+ UINT8 *PtrBuf;
+ UINTN PtrEnd;
+
+ PtrBuf = Buffer;
+ PtrEnd = (UINTN)Buffer + BufferSize;
+
+ //
+ // 0x0D indicates a line break. Otherwise there is no line break
+ //
+ while ((UINTN)PtrBuf < PtrEnd) {
+ if (*PtrBuf == 0x0D) {
+ break;
+ }
+ PtrBuf++;
+ }
+
+ if ((UINTN)PtrBuf >= (PtrEnd - 1)) {
+ //
+ // The buffer ends without any line break
+ // or it is the last character of the buffer
+ //
+ Length = BufferSize;
+ } else if (*(PtrBuf + 1) == 0x0A) {
+ //
+ // Further check if a 0x0A follows. If yes, count 0xA
+ //
+ Length = (UINTN) PtrBuf - (UINTN) Buffer + 2;
+ } else {
+ Length = (UINTN) PtrBuf - (UINTN) Buffer + 1;
+ }
+
+ if (Length > (*LineSize)) {
+ *LineSize = Length;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ SetMem (LineBuffer, *LineSize, 0x0);
+ *LineSize = Length;
+ CopyMem (LineBuffer, Buffer, Length);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Trim Buffer by removing all CR, LF, TAB, and SPACE chars in its head and tail.
+
+ @param Buffer On input, buffer data to be trimed.
+ On output, the trimmed buffer.
+ @param BufferSize On input, size of original buffer data.
+ On output, size of the trimmed buffer.
+
+**/
+VOID
+ProfileTrim (
+ IN OUT UINT8 *Buffer,
+ IN OUT UINTN *BufferSize
+ )
+{
+ UINTN Length;
+ UINT8 *PtrBuf;
+ UINT8 *PtrEnd;
+
+ if (*BufferSize == 0) {
+ return;
+ }
+
+ //
+ // Trim the tail first, include CR, LF, TAB, and SPACE.
+ //
+ Length = *BufferSize;
+ PtrBuf = (UINT8 *) ((UINTN) Buffer + Length - 1);
+ while (PtrBuf >= Buffer) {
+ if ((*PtrBuf != 0x0D) && (*PtrBuf != 0x0A )
+ && (*PtrBuf != 0x20) && (*PtrBuf != 0x09)) {
+ break;
+ }
+ PtrBuf --;
+ }
+
+ //
+ // all spaces, a blank line, return directly;
+ //
+ if (PtrBuf < Buffer) {
+ *BufferSize = 0;
+ return;
+ }
+
+ Length = (UINTN)PtrBuf - (UINTN)Buffer + 1;
+ PtrEnd = PtrBuf;
+ PtrBuf = Buffer;
+
+ //
+ // Now skip the heading CR, LF, TAB and SPACE
+ //
+ while (PtrBuf <= PtrEnd) {
+ if ((*PtrBuf != 0x0D) && (*PtrBuf != 0x0A )
+ && (*PtrBuf != 0x20) && (*PtrBuf != 0x09)) {
+ break;
+ }
+ PtrBuf++;
+ }
+
+ //
+ // If no heading CR, LF, TAB or SPACE, directly return
+ //
+ if (PtrBuf == Buffer) {
+ *BufferSize = Length;
+ return;
+ }
+
+ *BufferSize = (UINTN)PtrEnd - (UINTN)PtrBuf + 1;
+
+ //
+ // The first Buffer..PtrBuf characters are CR, LF, TAB or SPACE.
+ // Now move out all these characters.
+ //
+ while (PtrBuf <= PtrEnd) {
+ *Buffer = *PtrBuf;
+ Buffer++;
+ PtrBuf++;
+ }
+
+ return;
+}
+
+/**
+ Insert new comment item into comment head.
+
+ @param Buffer Comment buffer to be added.
+ @param BufferSize Size of comment buffer.
+ @param CommentHead Comment Item head entry.
+
+ @retval EFI_OUT_OF_RESOURCES No enough memory is allocated.
+ @retval EFI_SUCCESS New comment item is inserted.
+
+**/
+EFI_STATUS
+ProfileGetComments (
+ IN UINT8 *Buffer,
+ IN UINTN BufferSize,
+ IN OUT COMMENT_LINE **CommentHead
+ )
+{
+ COMMENT_LINE *CommentItem;
+
+ CommentItem = NULL;
+ CommentItem = AllocatePool (sizeof (COMMENT_LINE));
+ if (CommentItem == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ CommentItem->ptrNext = *CommentHead;
+ *CommentHead = CommentItem;
+
+ //
+ // Add a trailing '\0'
+ //
+ CommentItem->ptrComment = AllocatePool (BufferSize + 1);
+ if (CommentItem->ptrComment == NULL) {
+ FreePool (CommentItem);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ CopyMem (CommentItem->ptrComment, Buffer, BufferSize);
+ *(CommentItem->ptrComment + BufferSize) = '\0';
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Add new section item into Section head.
+
+ @param Buffer Section item data buffer.
+ @param BufferSize Size of section item.
+ @param SectionHead Section item head entry.
+
+ @retval EFI_OUT_OF_RESOURCES No enough memory is allocated.
+ @retval EFI_SUCCESS Section item is NULL or Section item is added.
+
+**/
+EFI_STATUS
+ProfileGetSection (
+ IN UINT8 *Buffer,
+ IN UINTN BufferSize,
+ IN OUT SECTION_ITEM **SectionHead
+ )
+{
+ EFI_STATUS Status;
+ SECTION_ITEM *SectionItem;
+ UINTN Length;
+ UINT8 *PtrBuf;
+
+ Status = EFI_SUCCESS;
+ //
+ // The first character of Buffer is '[', now we want for ']'
+ //
+ PtrBuf = (UINT8 *)((UINTN)Buffer + BufferSize - 1);
+ while (PtrBuf > Buffer) {
+ if (*PtrBuf == ']') {
+ break;
+ }
+ PtrBuf --;
+ }
+ if (PtrBuf <= Buffer) {
+ //
+ // Not found. Omit this line
+ //
+ return Status;
+ }
+
+ //
+ // excluding the heading '[' and tailing ']'
+ //
+ Length = PtrBuf - Buffer - 1;
+ ProfileTrim (
+ Buffer + 1,
+ &Length
+ );
+
+ //
+ // omit this line if the section name is null
+ //
+ if (Length == 0) {
+ return Status;
+ }
+
+ SectionItem = AllocatePool (sizeof (SECTION_ITEM));
+ if (SectionItem == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ SectionItem->ptrSection = NULL;
+ SectionItem->SecNameLen = Length;
+ SectionItem->ptrEntry = NULL;
+ SectionItem->ptrValue = NULL;
+ SectionItem->ptrNext = *SectionHead;
+ *SectionHead = SectionItem;
+
+ //
+ // Add a trailing '\0'
+ //
+ SectionItem->ptrSection = AllocatePool (Length + 1);
+ if (SectionItem->ptrSection == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // excluding the heading '['
+ //
+ CopyMem (SectionItem->ptrSection, Buffer + 1, Length);
+ *(SectionItem->ptrSection + Length) = '\0';
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Add new section entry and entry value into Section head.
+
+ @param Buffer Section entry data buffer.
+ @param BufferSize Size of section entry.
+ @param SectionHead Section item head entry.
+
+ @retval EFI_OUT_OF_RESOURCES No enough memory is allocated.
+ @retval EFI_SUCCESS Section entry is NULL or Section entry is added.
+
+**/
+EFI_STATUS
+ProfileGetEntry (
+ IN UINT8 *Buffer,
+ IN UINTN BufferSize,
+ IN OUT SECTION_ITEM **SectionHead
+ )
+{
+ EFI_STATUS Status;
+ SECTION_ITEM *SectionItem;
+ SECTION_ITEM *PtrSection;
+ UINTN Length;
+ UINT8 *PtrBuf;
+ UINT8 *PtrEnd;
+
+ Status = EFI_SUCCESS;
+ PtrBuf = Buffer;
+ PtrEnd = (UINT8 *) ((UINTN)Buffer + BufferSize - 1);
+
+ //
+ // First search for '='
+ //
+ while (PtrBuf <= PtrEnd) {
+ if (*PtrBuf == '=') {
+ break;
+ }
+ PtrBuf++;
+ }
+ if (PtrBuf > PtrEnd) {
+ //
+ // Not found. Omit this line
+ //
+ return Status;
+ }
+
+ //
+ // excluding the tailing '='
+ //
+ Length = PtrBuf - Buffer;
+ ProfileTrim (
+ Buffer,
+ &Length
+ );
+
+ //
+ // Omit this line if the entry name is null
+ //
+ if (Length == 0) {
+ return Status;
+ }
+
+ //
+ // Omit this line if no section header has been found before
+ //
+ if (*SectionHead == NULL) {
+ return Status;
+ }
+ PtrSection = *SectionHead;
+
+ SectionItem = AllocatePool (sizeof (SECTION_ITEM));
+ if (SectionItem == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ SectionItem->ptrSection = NULL;
+ SectionItem->ptrEntry = NULL;
+ SectionItem->ptrValue = NULL;
+ SectionItem->SecNameLen = PtrSection->SecNameLen;
+ SectionItem->ptrNext = *SectionHead;
+ *SectionHead = SectionItem;
+
+ //
+ // SectionName, add a trailing '\0'
+ //
+ SectionItem->ptrSection = AllocatePool (PtrSection->SecNameLen + 1);
+ if (SectionItem->ptrSection == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ CopyMem (SectionItem->ptrSection, PtrSection->ptrSection, PtrSection->SecNameLen + 1);
+
+ //
+ // EntryName, add a trailing '\0'
+ //
+ SectionItem->ptrEntry = AllocatePool (Length + 1);
+ if (SectionItem->ptrEntry == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ CopyMem (SectionItem->ptrEntry, Buffer, Length);
+ *(SectionItem->ptrEntry + Length) = '\0';
+
+ //
+ // Next search for '#'
+ //
+ PtrBuf = PtrBuf + 1;
+ Buffer = PtrBuf;
+ while (PtrBuf <= PtrEnd) {
+ if (*PtrBuf == '#') {
+ break;
+ }
+ PtrBuf++;
+ }
+ Length = PtrBuf - Buffer;
+ ProfileTrim (
+ Buffer,
+ &Length
+ );
+
+ if (Length > 0) {
+ //
+ // EntryValue, add a trailing '\0'
+ //
+ SectionItem->ptrValue = AllocatePool (Length + 1);
+ if (SectionItem->ptrValue == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ CopyMem (SectionItem->ptrValue, Buffer, Length);
+ *(SectionItem->ptrValue + Length) = '\0';
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Free all comment entry and section entry.
+
+ @param Section Section entry list.
+ @param Comment Comment entry list.
+
+**/
+VOID
+FreeAllList (
+ IN SECTION_ITEM *Section,
+ IN COMMENT_LINE *Comment
+ )
+{
+ SECTION_ITEM *PtrSection;
+ COMMENT_LINE *PtrComment;
+
+ while (Section != NULL) {
+ PtrSection = Section;
+ Section = Section->ptrNext;
+ if (PtrSection->ptrEntry != NULL) {
+ FreePool (PtrSection->ptrEntry);
+ }
+ if (PtrSection->ptrSection != NULL) {
+ FreePool (PtrSection->ptrSection);
+ }
+ if (PtrSection->ptrValue != NULL) {
+ FreePool (PtrSection->ptrValue);
+ }
+ FreePool (PtrSection);
+ }
+
+ while (Comment != NULL) {
+ PtrComment = Comment;
+ Comment = Comment->ptrNext;
+ if (PtrComment->ptrComment != NULL) {
+ FreePool (PtrComment->ptrComment);
+ }
+ FreePool (PtrComment);
+ }
+
+ return;
+}
+
+/**
+ Get section entry value.
+
+ @param Section Section entry list.
+ @param SectionName Section name.
+ @param EntryName Section entry name.
+ @param EntryValue Point to the got entry value.
+
+ @retval EFI_NOT_FOUND Section is not found.
+ @retval EFI_SUCCESS Section entry value is got.
+
+**/
+EFI_STATUS
+UpdateGetProfileString (
+ IN SECTION_ITEM *Section,
+ IN UINT8 *SectionName,
+ IN UINT8 *EntryName,
+ OUT UINT8 **EntryValue
+ )
+{
+ *EntryValue = NULL;
+
+ while (Section != NULL) {
+ if (AsciiStrCmp ((CONST CHAR8 *) Section->ptrSection, (CONST CHAR8 *) SectionName) == 0) {
+ if (Section->ptrEntry != NULL) {
+ if (AsciiStrCmp ((CONST CHAR8 *) Section->ptrEntry, (CONST CHAR8 *) EntryName) == 0) {
+ break;
+ }
+ }
+ }
+ Section = Section->ptrNext;
+ }
+
+ if (Section == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ *EntryValue = (UINT8 *) Section->ptrValue;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Convert the dec or hex ascii string to value.
+
+ @param Str ascii string to be converted.
+
+ @return the converted value.
+
+**/
+UINTN
+UpdateAtoi (
+ IN UINT8 *Str
+ )
+{
+ UINTN Number;
+
+ Number = 0;
+
+ //
+ // Skip preceeding while spaces
+ //
+ while (*Str != '\0') {
+ if (*Str != 0x20) {
+ break;
+ }
+ Str++;
+ }
+
+ if (*Str == '\0') {
+ return Number;
+ }
+
+ //
+ // Find whether the string is prefixed by 0x.
+ // That is, it should be xtoi or atoi.
+ //
+ if (*Str == '0') {
+ if ((*(Str+1) == 'x' ) || ( *(Str+1) == 'X')) {
+ return AsciiStrHexToUintn ((CONST CHAR8 *) Str);
+ }
+ }
+
+ while (*Str != '\0') {
+ if ((*Str >= '0') && (*Str <= '9')) {
+ Number = Number * 10 + *Str - '0';
+ } else {
+ break;
+ }
+ Str++;
+ }
+
+ return Number;
+}
+
+/**
+ Converts a decimal value to a Null-terminated ascii string.
+
+ @param Buffer Pointer to the output buffer for the produced Null-terminated
+ ASCII string.
+ @param Value The 64-bit sgned value to convert to a string.
+
+ @return The number of ASCII characters in Buffer not including the Null-terminator.
+
+**/
+UINTN
+UpdateValueToString (
+ IN OUT UINT8 *Buffer,
+ IN INT64 Value
+ )
+{
+ UINT8 TempBuffer[30];
+ UINT8 *TempStr;
+ UINT8 *BufferPtr;
+ UINTN Count;
+ UINT32 Remainder;
+
+ TempStr = TempBuffer;
+ BufferPtr = Buffer;
+ Count = 0;
+
+ if (Value < 0) {
+ *BufferPtr = '-';
+ BufferPtr++;
+ Value = -Value;
+ Count++;
+ }
+
+ do {
+ Value = (INT64) DivU64x32Remainder ((UINT64)Value, 10, &Remainder);
+ //
+ // The first item of TempStr is not occupied. It's kind of flag
+ //
+ TempStr++;
+ Count++;
+ *TempStr = (UINT8) ((UINT8)Remainder + '0');
+ } while (Value != 0);
+
+ //
+ // Reverse temp string into Buffer.
+ //
+ while (TempStr != TempBuffer) {
+ *BufferPtr = *TempStr;
+ BufferPtr++;
+ TempStr --;
+ }
+
+ *BufferPtr = 0;
+
+ return Count;
+}
+
+/**
+ Convert the input value to a ascii string,
+ and concatenates this string to the input string.
+
+ @param Str Pointer to a Null-terminated ASCII string.
+ @param Number The unsgned value to convert to a string.
+
+**/
+VOID
+UpdateStrCatNumber (
+ IN OUT UINT8 *Str,
+ IN UINTN Number
+ )
+{
+ UINTN Count;
+
+ while (*Str != '\0') {
+ Str++;
+ }
+
+ Count = UpdateValueToString (Str, (INT64)Number);
+
+ *(Str + Count) = '\0';
+
+ return;
+}
+
+/**
+ Convert the input ascii string into GUID value.
+
+ @param Str Ascii GUID string to be converted.
+ @param Guid Pointer to the converted GUID value.
+
+ @retval EFI_OUT_OF_RESOURCES No enough memory is allocated.
+ @retval EFI_NOT_FOUND The input ascii string is not a valid GUID format string.
+ @retval EFI_SUCCESS GUID value is got.
+
+**/
+EFI_STATUS
+UpdateStringToGuid (
+ IN UINT8 *Str,
+ IN OUT EFI_GUID *Guid
+ )
+{
+ UINT8 *PtrBuffer;
+ UINT8 *PtrPosition;
+ UINT8 *Buffer;
+ UINTN Data;
+ UINTN StrLen;
+ UINTN Index;
+ UINT8 Digits[3];
+
+ StrLen = AsciiStrLen ((CONST CHAR8 *) Str);
+ Buffer = AllocatePool (StrLen + 1);
+ if (Buffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ AsciiStrCpy ((CHAR8 *)Buffer, (CHAR8 *)Str);
+
+ //
+ // Data1
+ //
+ PtrBuffer = Buffer;
+ PtrPosition = PtrBuffer;
+ while (*PtrBuffer != '\0') {
+ if (*PtrBuffer == '-') {
+ break;
+ }
+ PtrBuffer++;
+ }
+ if (*PtrBuffer == '\0') {
+ FreePool (Buffer);
+ return EFI_NOT_FOUND;
+ }
+
+ *PtrBuffer = '\0';
+ Data = AsciiStrHexToUintn ((CONST CHAR8 *) PtrPosition);
+ Guid->Data1 = (UINT32)Data;
+
+ //
+ // Data2
+ //
+ PtrBuffer++;
+ PtrPosition = PtrBuffer;
+ while (*PtrBuffer != '\0') {
+ if (*PtrBuffer == '-') {
+ break;
+ }
+ PtrBuffer++;
+ }
+ if (*PtrBuffer == '\0') {
+ FreePool (Buffer);
+ return EFI_NOT_FOUND;
+ }
+ *PtrBuffer = '\0';
+ Data = AsciiStrHexToUintn ((CONST CHAR8 *) PtrPosition);
+ Guid->Data2 = (UINT16)Data;
+
+ //
+ // Data3
+ //
+ PtrBuffer++;
+ PtrPosition = PtrBuffer;
+ while (*PtrBuffer != '\0') {
+ if (*PtrBuffer == '-') {
+ break;
+ }
+ PtrBuffer++;
+ }
+ if (*PtrBuffer == '\0') {
+ FreePool (Buffer);
+ return EFI_NOT_FOUND;
+ }
+ *PtrBuffer = '\0';
+ Data = AsciiStrHexToUintn ((CONST CHAR8 *) PtrPosition);
+ Guid->Data3 = (UINT16)Data;
+
+ //
+ // Data4[0..1]
+ //
+ for ( Index = 0 ; Index < 2 ; Index++) {
+ PtrBuffer++;
+ if ((*PtrBuffer == '\0') || ( *(PtrBuffer + 1) == '\0')) {
+ FreePool (Buffer);
+ return EFI_NOT_FOUND;
+ }
+ Digits[0] = *PtrBuffer;
+ PtrBuffer++;
+ Digits[1] = *PtrBuffer;
+ Digits[2] = '\0';
+ Data = AsciiStrHexToUintn ((CONST CHAR8 *) Digits);
+ Guid->Data4[Index] = (UINT8)Data;
+ }
+
+ //
+ // skip the '-'
+ //
+ PtrBuffer++;
+ if ((*PtrBuffer != '-' ) || ( *PtrBuffer == '\0')) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Data4[2..7]
+ //
+ for ( ; Index < 8; Index++) {
+ PtrBuffer++;
+ if ((*PtrBuffer == '\0') || ( *(PtrBuffer + 1) == '\0')) {
+ FreePool (Buffer);
+ return EFI_NOT_FOUND;
+ }
+ Digits[0] = *PtrBuffer;
+ PtrBuffer++;
+ Digits[1] = *PtrBuffer;
+ Digits[2] = '\0';
+ Data = AsciiStrHexToUintn ((CONST CHAR8 *) Digits);
+ Guid->Data4[Index] = (UINT8)Data;
+ }
+
+ FreePool (Buffer);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Pre process config data buffer into Section entry list and Comment entry list.
+
+ @param DataBuffer Config raw file buffer.
+ @param BufferSize Size of raw buffer.
+ @param SectionHead Pointer to the section entry list.
+ @param CommentHead Pointer to the comment entry list.
+
+ @retval EFI_OUT_OF_RESOURCES No enough memory is allocated.
+ @retval EFI_SUCCESS Config data buffer is preprocessed.
+
+**/
+EFI_STATUS
+PreProcessDataFile (
+ IN UINT8 *DataBuffer,
+ IN UINTN BufferSize,
+ IN OUT SECTION_ITEM **SectionHead,
+ IN OUT COMMENT_LINE **CommentHead
+ )
+{
+ EFI_STATUS Status;
+ CHAR8 *Source;
+ CHAR8 *CurrentPtr;
+ CHAR8 *BufferEnd;
+ CHAR8 *PtrLine;
+ UINTN LineLength;
+ UINTN SourceLength;
+ UINTN MaxLineLength;
+
+ *SectionHead = NULL;
+ *CommentHead = NULL;
+ BufferEnd = (CHAR8 *) ( (UINTN) DataBuffer + BufferSize);
+ CurrentPtr = (CHAR8 *) DataBuffer;
+ MaxLineLength = MAX_LINE_LENGTH;
+ Status = EFI_SUCCESS;
+
+ PtrLine = AllocatePool (MaxLineLength);
+ if (PtrLine == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ while (CurrentPtr < BufferEnd) {
+ Source = CurrentPtr;
+ SourceLength = (UINTN)BufferEnd - (UINTN)CurrentPtr;
+ LineLength = MaxLineLength;
+ //
+ // With the assumption that line length is less than 512
+ // characters. Otherwise BUFFER_TOO_SMALL will be returned.
+ //
+ Status = ProfileGetLine (
+ (UINT8 *) Source,
+ SourceLength,
+ (UINT8 *) PtrLine,
+ &LineLength
+ );
+ if (EFI_ERROR (Status)) {
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ //
+ // If buffer too small, re-allocate the buffer according
+ // to the returned LineLength and try again.
+ //
+ FreePool (PtrLine);
+ PtrLine = NULL;
+ PtrLine = AllocatePool (LineLength);
+ if (PtrLine == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ break;
+ }
+ SourceLength = LineLength;
+ Status = ProfileGetLine (
+ (UINT8 *) Source,
+ SourceLength,
+ (UINT8 *) PtrLine,
+ &LineLength
+ );
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+ MaxLineLength = LineLength;
+ } else {
+ break;
+ }
+ }
+ CurrentPtr = (CHAR8 *) ( (UINTN) CurrentPtr + LineLength);
+
+ //
+ // Line got. Trim the line before processing it.
+ //
+ ProfileTrim (
+ (UINT8 *) PtrLine,
+ &LineLength
+ );
+
+ //
+ // Blank line
+ //
+ if (LineLength == 0) {
+ continue;
+ }
+
+ if (PtrLine[0] == '#') {
+ Status = ProfileGetComments (
+ (UINT8 *) PtrLine,
+ LineLength,
+ CommentHead
+ );
+ } else if (PtrLine[0] == '[') {
+ Status = ProfileGetSection (
+ (UINT8 *) PtrLine,
+ LineLength,
+ SectionHead
+ );
+ } else {
+ Status = ProfileGetEntry (
+ (UINT8 *) PtrLine,
+ LineLength,
+ SectionHead
+ );
+ }
+
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+ }
+
+ //
+ // Free buffer
+ //
+ FreePool (PtrLine);
+
+ return Status;
+}
+
+/**
+ Parse Config data file to get the updated data array.
+
+ @param DataBuffer Config raw file buffer.
+ @param BufferSize Size of raw buffer.
+ @param NumOfUpdates Pointer to the number of update data.
+ @param UpdateArray Pointer to the config of update data.
+
+ @retval EFI_NOT_FOUND No config data is found.
+ @retval EFI_OUT_OF_RESOURCES No enough memory is allocated.
+ @retval EFI_SUCCESS Parse the config file successfully.
+
+**/
+EFI_STATUS
+ParseUpdateDataFile (
+ IN UINT8 *DataBuffer,
+ IN UINTN BufferSize,
+ IN OUT UINTN *NumOfUpdates,
+ IN OUT UPDATE_CONFIG_DATA **UpdateArray
+ )
+{
+ EFI_STATUS Status;
+ CHAR8 *Value;
+ CHAR8 *SectionName;
+ CHAR8 Entry[MAX_LINE_LENGTH];
+ SECTION_ITEM *SectionHead;
+ COMMENT_LINE *CommentHead;
+ UINTN Num;
+ UINTN Index;
+ EFI_GUID FileGuid;
+
+ SectionHead = NULL;
+ CommentHead = NULL;
+
+ //
+ // First process the data buffer and get all sections and entries
+ //
+ Status = PreProcessDataFile (
+ DataBuffer,
+ BufferSize,
+ &SectionHead,
+ &CommentHead
+ );
+ if (EFI_ERROR (Status)) {
+ FreeAllList (SectionHead, CommentHead);
+ return Status;
+ }
+
+ //
+ // Now get NumOfUpdate
+ //
+ Value = NULL;
+ Status = UpdateGetProfileString (
+ SectionHead,
+ (UINT8 *) "Head",
+ (UINT8 *) "NumOfUpdate",
+ (UINT8 **) &Value
+ );
+ if (Value == NULL) {
+ FreeAllList (SectionHead, CommentHead);
+ return EFI_NOT_FOUND;
+ }
+ Num = UpdateAtoi((UINT8 *) Value);
+ if (Num <= 0) {
+ FreeAllList (SectionHead, CommentHead);
+ return EFI_NOT_FOUND;
+ }
+
+ *NumOfUpdates = Num;
+ *UpdateArray = AllocatePool ((sizeof (UPDATE_CONFIG_DATA) * Num));
+ if (*UpdateArray == NULL) {
+ FreeAllList (SectionHead, CommentHead);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ for ( Index = 0 ; Index < *NumOfUpdates ; Index++) {
+ //
+ // Get the section name of each update
+ //
+ AsciiStrCpy (Entry, "Update");
+ UpdateStrCatNumber ((UINT8 *) Entry, Index);
+ Value = NULL;
+ Status = UpdateGetProfileString (
+ SectionHead,
+ (UINT8 *) "Head",
+ (UINT8 *) Entry,
+ (UINT8 **) &Value
+ );
+ if (Value == NULL) {
+ FreeAllList (SectionHead, CommentHead);
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // The section name of this update has been found.
+ // Now looks for all the config data of this update
+ //
+ SectionName = Value;
+
+ //
+ // UpdateType
+ //
+ Value = NULL;
+ Status = UpdateGetProfileString (
+ SectionHead,
+ (UINT8 *) SectionName,
+ (UINT8 *) "UpdateType",
+ (UINT8 **) &Value
+ );
+ if (Value == NULL) {
+ FreeAllList (SectionHead, CommentHead);
+ return EFI_NOT_FOUND;
+ }
+
+ Num = UpdateAtoi((UINT8 *) Value);
+ if (( Num >= (UINTN) UpdateOperationMaximum)) {
+ FreeAllList (SectionHead, CommentHead);
+ return Status;
+ }
+ (*UpdateArray)[Index].Index = Index;
+ (*UpdateArray)[Index].UpdateType = (UPDATE_OPERATION_TYPE) Num;
+
+ //
+ // FvBaseAddress
+ //
+ Value = NULL;
+ Status = UpdateGetProfileString (
+ SectionHead,
+ (UINT8 *) SectionName,
+ (UINT8 *) "FvBaseAddress",
+ (UINT8 **) &Value
+ );
+ if (Value == NULL) {
+ FreeAllList (SectionHead, CommentHead);
+ return EFI_NOT_FOUND;
+ }
+
+ Num = AsciiStrHexToUintn ((CONST CHAR8 *) Value);
+ (*UpdateArray)[Index].BaseAddress = (EFI_PHYSICAL_ADDRESS) Num;
+
+ //
+ // FileBuid
+ //
+ Value = NULL;
+ Status = UpdateGetProfileString (
+ SectionHead,
+ (UINT8 *) SectionName,
+ (UINT8 *) "FileGuid",
+ (UINT8 **) &Value
+ );
+ if (Value == NULL) {
+ FreeAllList (SectionHead, CommentHead);
+ return EFI_NOT_FOUND;
+ }
+
+ Status = UpdateStringToGuid ((UINT8 *) Value, &FileGuid);
+ if (EFI_ERROR (Status)) {
+ FreeAllList (SectionHead, CommentHead);
+ return Status;
+ }
+ CopyMem (&((*UpdateArray)[Index].FileGuid), &FileGuid, sizeof(EFI_GUID));
+
+ //
+ // FaultTolerant
+ // Default value is FALSE
+ //
+ Value = NULL;
+ (*UpdateArray)[Index].FaultTolerant = FALSE;
+ Status = UpdateGetProfileString (
+ SectionHead,
+ (UINT8 *) SectionName,
+ (UINT8 *) "FaultTolerant",
+ (UINT8 **) &Value
+ );
+ if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
+ FreeAllList (SectionHead, CommentHead);
+ return Status;
+ } else if (Value != NULL) {
+ if (AsciiStriCmp ((CONST CHAR8 *) Value, (CONST CHAR8 *) "TRUE") == 0) {
+ (*UpdateArray)[Index].FaultTolerant = TRUE;
+ } else if (AsciiStriCmp ((CONST CHAR8 *) Value, (CONST CHAR8 *) "FALSE") == 0) {
+ (*UpdateArray)[Index].FaultTolerant = FALSE;
+ }
+ }
+
+ if ((*UpdateArray)[Index].UpdateType == UpdateFvRange) {
+ //
+ // Length
+ //
+ Value = NULL;
+ Status = UpdateGetProfileString (
+ SectionHead,
+ (UINT8 *) SectionName,
+ (UINT8 *) "Length",
+ (UINT8 **) &Value
+ );
+ if (Value == NULL) {
+ FreeAllList (SectionHead, CommentHead);
+ return EFI_NOT_FOUND;
+ }
+
+ Num = AsciiStrHexToUintn ((CONST CHAR8 *) Value);
+ (*UpdateArray)[Index].Length = (UINTN) Num;
+ }
+ }
+
+ //
+ // Now all configuration data got. Free those temporary buffers
+ //
+ FreeAllList (SectionHead, CommentHead);
+
+ return EFI_SUCCESS;
+}
+
diff --git a/Vlv2TbltDevicePkg/UpdateDriverDxe/UpdateDispatcher.c b/Vlv2TbltDevicePkg/UpdateDriverDxe/UpdateDispatcher.c
new file mode 100644
index 0000000000..f189bc109d
--- /dev/null
+++ b/Vlv2TbltDevicePkg/UpdateDriverDxe/UpdateDispatcher.c
@@ -0,0 +1,897 @@
+/** @file
+ Functions in this file will mainly focus on looking through the capsule
+ for the image to be programmed, and the flash area that is going to be
+ programed.
+
+ Copyright (c) 2004 - 2016, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ 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 "UpdateDriver.h"
+
+EFI_HII_HANDLE gHiiHandle;
+EFI_SYSTEM_RESOURCE_ENTRY NewEsrtTemplate =
+ // System Firmware Entry
+ {
+ SYSTEM_FW_CLASS_GUID,
+ ESRT_FW_TYPE_SYSTEMFIRMWARE,
+ 0x0003,
+ 0x0001,
+ 0x0000,
+ 0x0003,
+ LAST_ATTEMPT_STATUS_SUCCESS
+ };
+
+/**
+ Update the whole FV, or certain files in the FV.
+
+ @param ConfigData Pointer to the config data on updating file.
+ @param ImageBuffer Image buffer to be updated.
+ @param ImageSize Image size.
+ @param FileType FFS file type.
+ @param FileAttributes FFS file attribute.
+
+ @retval EFI_NOT_FOUND The matched FVB protocol is not found.
+ @retval EFI_SUCCESS The image buffer is updated into FV.
+
+**/
+EFI_STATUS
+PerformUpdateOnFirmwareVolume (
+ IN UPDATE_CONFIG_DATA *ConfigData,
+ IN UINT8 *ImageBuffer,
+ IN UINTN ImageSize,
+ IN EFI_FV_FILETYPE FileType,
+ IN EFI_FV_FILE_ATTRIBUTES FileAttributes
+ )
+{
+ EFI_STATUS Status;
+ BOOLEAN Found;
+ EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvbProtocol;
+ UINTN Index;
+ UINTN NumOfHandles;
+ EFI_HANDLE *HandleBuffer;
+ EFI_PHYSICAL_ADDRESS BaseAddress;
+ EFI_FVB_ATTRIBUTES_2 Attributes;
+
+ //
+ // Locate all Fvb protocol
+ //
+ HandleBuffer = NULL;
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiFirmwareVolumeBlockProtocolGuid,
+ NULL,
+ &NumOfHandles,
+ &HandleBuffer
+ );
+ if ((EFI_ERROR (Status)) || (NumOfHandles == 0) || (HandleBuffer == NULL)) {
+ if (HandleBuffer != NULL) {
+ FreePool (HandleBuffer);
+ }
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Check the FVB protocol one by one
+ //
+ Found = FALSE;
+ FvbProtocol = NULL;
+ for (Index = 0; Index < NumOfHandles; Index++) {
+ Status = gBS->HandleProtocol (
+ HandleBuffer[Index],
+ &gEfiFirmwareVolumeBlockProtocolGuid,
+ (VOID **) &FvbProtocol
+ );
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+
+ //
+ // Ensure this FVB protocol supported Write operation.
+ //
+ Status = FvbProtocol->GetAttributes (FvbProtocol, &Attributes);
+ if (EFI_ERROR (Status) || ((Attributes & EFI_FVB2_WRITE_STATUS) == 0)) {
+ continue;
+ }
+
+ Status = FvbProtocol->GetPhysicalAddress (
+ FvbProtocol,
+ &BaseAddress
+ );
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+ if (BaseAddress == ConfigData->BaseAddress) {
+ Found = TRUE;
+ break;
+ }
+ }
+
+ if (!Found) {
+ if (HandleBuffer != NULL) {
+ FreePool (HandleBuffer);
+ HandleBuffer = NULL;
+ }
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Now we have got the corresponding FVB protocol. Use the FVB protocol
+ // to update the whole FV, or certain files in the FV.
+ //
+ if (ConfigData->UpdateType == UpdateWholeFV) {
+ if (FileType != EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE) {
+ Status = EFI_INVALID_PARAMETER;
+ } else {
+ Status = PerformUpdateOnWholeFv (
+ HandleBuffer[Index],
+ FvbProtocol,
+ ConfigData,
+ ImageBuffer,
+ ImageSize
+ );
+ }
+ } else if (ConfigData->UpdateType == UpdateFvFile) {
+ Status = PerformUpdateOnFvFile (
+ HandleBuffer[Index],
+ FvbProtocol,
+ ConfigData,
+ ImageBuffer,
+ ImageSize,
+ FileType,
+ FileAttributes
+ );
+ }
+
+ if (HandleBuffer != NULL) {
+ FreePool (HandleBuffer);
+ HandleBuffer = NULL;
+ }
+
+ return Status;
+}
+
+/**
+ Update the file directly into flash area.
+
+ @param ConfigData Pointer to the config data on updating file.
+ @param ImageBuffer Image buffer to be updated.
+ @param ImageSize Image size.
+
+ @retval EFI_SUCCESS The file is updated into flash area.
+ @retval EFI_NOT_FOUND The FVB protocol for the updated flash area is not found.
+
+**/
+EFI_STATUS
+PerformUpdateOnFlashArea (
+ IN UPDATE_CONFIG_DATA *ConfigData,
+ IN UINT8 *ImageBuffer,
+ IN UINTN ImageSize
+ )
+{
+ EFI_STATUS Status;
+ UINTN SizeLeft;
+ EFI_PHYSICAL_ADDRESS FlashAddress;
+ UINT8 *PtrImage;
+ BOOLEAN Found;
+ EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvbProtocol;
+ UINTN Index;
+ UINTN NumOfHandles;
+ EFI_HANDLE *HandleBuffer;
+ EFI_PHYSICAL_ADDRESS BaseAddress;
+ EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
+ EFI_HANDLE FvbHandle;
+ UINTN SizeUpdated;
+ CHAR16 *TmpStr;
+ EFI_FVB_ATTRIBUTES_2 Attributes;
+
+ SizeLeft = ImageSize;
+ PtrImage = ImageBuffer;
+ FlashAddress = ConfigData->BaseAddress;
+ Status = EFI_SUCCESS;
+ HandleBuffer = NULL;
+
+ //
+ // Print on screen
+ //
+ TmpStr = HiiGetString (gHiiHandle, STRING_TOKEN(UPDATE_FLASH_RANGE), NULL);
+ if (TmpStr != NULL) {
+ Print (TmpStr, FlashAddress, ((UINT64)SizeLeft + FlashAddress));
+ FreePool (TmpStr);
+ }
+
+ //
+ // Locate all Fvb protocol
+ //
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiFirmwareVolumeBlockProtocolGuid,
+ NULL,
+ &NumOfHandles,
+ &HandleBuffer
+ );
+ if ((EFI_ERROR (Status)) || (NumOfHandles == 0) || (HandleBuffer == NULL)) {
+ if (HandleBuffer != NULL) {
+ FreePool (HandleBuffer);
+ }
+ return EFI_NOT_FOUND;
+ }
+
+ while (SizeLeft > 0) {
+ //
+ // First get the FVB protocols. If the flash area is a FV, or sub FV,
+ // we can directly locate all the FVB protocol. Otherwise we should use
+ // implementation specific method to get the alternate FVB protocol
+ //
+ Found = FALSE;
+ FvbProtocol = NULL;
+
+ //
+ // Check the FVB protocol one by one
+ //
+ for (Index = 0; Index < NumOfHandles; Index++) {
+ Status = gBS->HandleProtocol (
+ HandleBuffer[Index],
+ &gEfiFirmwareVolumeBlockProtocolGuid,
+ (VOID **) &FvbProtocol
+ );
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+
+ //
+ // Ensure this FVB protocol supported Write operation.
+ //
+ Status = FvbProtocol->GetAttributes (FvbProtocol, &Attributes);
+ if (EFI_ERROR (Status) || ((Attributes & EFI_FVB2_WRITE_STATUS) == 0)) {
+ continue;
+ }
+
+ Status = FvbProtocol->GetPhysicalAddress (
+ FvbProtocol,
+ &BaseAddress
+ );
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+ FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)BaseAddress;
+
+ //
+ // This sub area entry falls in the range of the FV
+ //
+ if ((FlashAddress >= BaseAddress) && (FlashAddress < (BaseAddress + FwVolHeader->FvLength))) {
+ Found = TRUE;
+ break;
+ }
+ }
+
+ if (!Found) {
+ if (HandleBuffer != NULL) {
+ FreePool (HandleBuffer);
+ HandleBuffer = NULL;
+ }
+ return EFI_NOT_FOUND;
+ }
+
+ FvbHandle = HandleBuffer[Index];
+ SizeUpdated = 0;
+
+ //
+ // If the flash area is boot required, the update must be fault tolerant
+ //
+ if (ConfigData->FaultTolerant) {
+ //
+ // Finally we are here. We have got the corresponding FVB protocol. Now
+ // we need to convert the physical address to LBA and offset and call
+ // FTW write. Also check if the flash range is larger than the FV.
+ //
+ Status = FaultTolerantUpdateOnPartFv (
+ PtrImage,
+ SizeLeft,
+ &SizeUpdated,
+ ConfigData,
+ FlashAddress,
+ FvbProtocol,
+ FvbHandle
+ );
+ } else {
+ //
+ // Finally we are here. We have got the corresponding FVB protocol. Now
+ // we need to convert the physical address to LBA and offset and call
+ // FVB write. Also check if the flash range is larger than the FV.
+ //
+ Status = NonFaultTolerantUpdateOnPartFv (
+ PtrImage,
+ SizeLeft,
+ &SizeUpdated,
+ FlashAddress,
+ FvbProtocol,
+ FvbHandle
+ );
+ }
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // As part of the FV has been replaced, the FV driver shall re-parse
+ // the firmware volume. So re-install FVB protocol here
+ //
+ Status = gBS->ReinstallProtocolInterface (
+ FvbHandle,
+ &gEfiFirmwareVolumeBlockProtocolGuid,
+ FvbProtocol,
+ FvbProtocol
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Check if we are done with the update
+ //
+ SizeLeft = SizeLeft - SizeUpdated;
+ FlashAddress = FlashAddress + SizeUpdated;
+ PtrImage = PtrImage + SizeUpdated;
+ }
+
+ if (HandleBuffer != NULL) {
+ FreePool (HandleBuffer);
+ HandleBuffer = NULL;
+ }
+
+ return Status;
+}
+
+/**
+ Find the updated file, and program it into the flash area based on the config data.
+
+ @param FwVolProtocol Pointer to FV protocol that contains the updated file.
+ @param ConfigData Pointer to the Config Data on updating file.
+
+ @retval EFI_INVALID_PARAMETER The update operation is not valid.
+ @retval EFI_NOT_FOUND The updated file is not found.
+ @retval EFI_SUCCESS The file is updated into the flash area.
+
+**/
+EFI_STATUS
+PerformUpdate (
+ IN EFI_FIRMWARE_VOLUME2_PROTOCOL *FwVolProtocol,
+ IN UPDATE_CONFIG_DATA *ConfigData
+ )
+{
+ EFI_STATUS Status;
+ UINT8 *FileBuffer;
+ UINTN FileBufferSize;
+ EFI_FV_FILETYPE FileType;
+ EFI_FV_FILE_ATTRIBUTES Attrib;
+ EFI_SECTION_TYPE SectionType;
+ UINT32 AuthenticationStatus;
+ CHAR16 *TmpStr;
+ BOOLEAN StartToUpdate;
+
+ Status = EFI_SUCCESS;
+ FileBuffer = NULL;
+ FileBufferSize = 0;
+ Status = FwVolProtocol->ReadFile (
+ FwVolProtocol,
+ &(ConfigData->FileGuid),
+ (VOID **) &FileBuffer,
+ &FileBufferSize,
+ &FileType,
+ &Attrib,
+ &AuthenticationStatus
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ StartToUpdate = FALSE;
+
+ //
+ // Check if the update image is the one we require
+ // and then perform the update
+ //
+ switch (ConfigData->UpdateType) {
+
+ case UpdateWholeFV:
+
+ //
+ // For UpdateWholeFv, the update file shall be a firmware volume
+ // image file.
+ //
+ if (FileType != EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE) {
+ DEBUG ((EFI_D_UPDATE, "UpdateDriver: Data file should be of TYPE EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE\n"));
+ Status = EFI_INVALID_PARAMETER;
+ } else {
+ if (FileBuffer != NULL) {
+ FreePool (FileBuffer);
+ }
+ SectionType = EFI_SECTION_FIRMWARE_VOLUME_IMAGE;
+ FileBuffer = NULL;
+ FileBufferSize = 0;
+ Status = FwVolProtocol->ReadSection (
+ FwVolProtocol,
+ &(ConfigData->FileGuid),
+ SectionType,
+ 0,
+ (VOID **) &FileBuffer,
+ &FileBufferSize,
+ &AuthenticationStatus
+ );
+ if (!EFI_ERROR (Status)) {
+ //
+ // Execute the update. For UpdateWholeFv, the update
+ // will always execute on a whole FV
+ //
+ StartToUpdate = TRUE;
+ Status = PerformUpdateOnFirmwareVolume (
+ ConfigData,
+ FileBuffer,
+ FileBufferSize,
+ FileType,
+ Attrib
+ );
+
+ } else {
+ DEBUG ((EFI_D_UPDATE, "UpdateDriver: Data file should be sectioned with TYPE EFI_SECTION_FIRMWARE_VOLUME_IMAGE\n"));
+ }
+ }
+ break;
+
+ case UpdateFvRange:
+
+ //
+ // For UpdateFvRange, the update file shall be a raw file
+ // which does not contain any sections. The contents of the file
+ // will be directly programmed.
+ //
+ if (FileType != EFI_FV_FILETYPE_RAW) {
+ DEBUG ((EFI_D_UPDATE, "UpdateDriver: Data file should of TYPE EFI_FV_FILETYPE_RAW\n"));
+ Status = EFI_INVALID_PARAMETER;
+ } else {
+ //
+ // For UpdateFvRange, the update may be performed on a sub area
+ // of a certain FV, or a flash area that is not FV, or part of FV.
+ // The update may also go across more than one FVs.
+ //
+ StartToUpdate = TRUE;
+ Status = PerformUpdateOnFlashArea (
+ ConfigData,
+ FileBuffer,
+ FileBufferSize
+ );
+ }
+ break;
+
+ case UpdateFvFile:
+
+ //
+ // No check will be done the the file got. The contents of the file
+ // will be directly programmed.
+ // Though UpdateFvFile will only update a single file, but the update
+ // will always execute on a FV
+ //
+ StartToUpdate = TRUE;
+ Status = PerformUpdateOnFirmwareVolume (
+ ConfigData,
+ FileBuffer,
+ FileBufferSize,
+ FileType,
+ Attrib
+ );
+ break;
+
+ default:
+ Status = EFI_INVALID_PARAMETER;
+ }
+
+ if (StartToUpdate) {
+ if (EFI_ERROR (Status)) {
+ TmpStr = HiiGetString (gHiiHandle, STRING_TOKEN(UPDATE_DRIVER_ABORTED), NULL);
+ } else {
+ TmpStr = HiiGetString (gHiiHandle, STRING_TOKEN(UPDATE_DRIVER_DONE), NULL);
+ }
+ if (TmpStr != NULL) {
+ Print (TmpStr);
+ FreePool (TmpStr);
+ }
+ }
+
+ if (FileBuffer != NULL) {
+ FreePool(FileBuffer);
+ FileBuffer = NULL;
+ }
+
+ return Status;
+}
+
+/**
+ Process the input firmware volume by using DXE service ProcessFirmwareVolume.
+
+ @param DataBuffer Point to the FV image to be processed.
+ @param BufferSize Size of the FV image buffer.
+ @param FwVolProtocol Point to the installed FV protocol for the input FV image.
+
+ @retval EFI_OUT_OF_RESOURCES No enough memory is allocated.
+ @retval EFI_VOLUME_CORRUPTED FV image is corrupted.
+ @retval EFI_SUCCESS FV image is processed and FV protocol is installed.
+
+**/
+EFI_STATUS
+ProcessUpdateImage (
+ UINT8 *DataBuffer,
+ UINTN BufferSize,
+ EFI_FIRMWARE_VOLUME2_PROTOCOL **FwVolProtocol
+ )
+{
+ EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
+ EFI_HANDLE FwVolHandle;
+ EFI_STATUS Status;
+ UINT8 *ProcessedDataBuffer;
+ UINT32 FvAlignment;
+
+ ProcessedDataBuffer = NULL;
+ FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) DataBuffer;
+ if (FwVolHeader->FvLength != BufferSize) {
+ return EFI_VOLUME_CORRUPTED;
+ }
+
+ FvAlignment = 1 << ((FwVolHeader->Attributes & EFI_FVB2_ALIGNMENT) >> 16);
+ //
+ // FvAlignment must be greater than or equal to 8 bytes of the minimum FFS alignment value.
+ //
+ if (FvAlignment < 8) {
+ FvAlignment = 8;
+ }
+ //
+ // Check FvImage Align is required.
+ //
+ if (((UINTN) FwVolHeader % FvAlignment) == 0) {
+ ProcessedDataBuffer = DataBuffer;
+ } else {
+ //
+ // Allocate new aligned buffer to store DataBuffer.
+ //
+ ProcessedDataBuffer = AllocateAlignedPages (EFI_SIZE_TO_PAGES (BufferSize), (UINTN) FvAlignment);
+ if (ProcessedDataBuffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ CopyMem (ProcessedDataBuffer, DataBuffer, BufferSize);
+ }
+ //
+ // Process the firmware volume
+ //
+ gDS->ProcessFirmwareVolume (
+ ProcessedDataBuffer,
+ BufferSize,
+ &FwVolHandle
+ );
+
+ //
+ // Get the FwVol protocol
+ //
+ Status = gBS->HandleProtocol (
+ FwVolHandle,
+ &gEfiFirmwareVolume2ProtocolGuid,
+ (VOID **) FwVolProtocol
+ );
+
+ return Status;
+}
+
+/**
+ Find the image in the same FV and program it in a target Firmware Volume device.
+ After update image, it will reset system and no return.
+
+ @param ImageHandle A handle for the image that is initializing this driver
+ @param SystemTable A pointer to the EFI system table
+
+ @retval EFI_ABORTED System reset failed.
+ @retval EFI_NOT_FOUND The updated image is not found in the same FV.
+
+**/
+EFI_STATUS
+EFIAPI
+InitializeUpdateDriver (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_STATUS StatusEsrt;
+ EFI_LOADED_IMAGE_PROTOCOL *LoadedImageProtocol;
+ EFI_FIRMWARE_VOLUME2_PROTOCOL *FwVolProtocol;
+ EFI_FIRMWARE_VOLUME2_PROTOCOL *DataFwVolProtocol;
+ MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FwVolFilePathNode;
+ MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *AlignedDevPathNode;
+ EFI_DEVICE_PATH_PROTOCOL *FilePathNode;
+ EFI_SECTION_TYPE SectionType;
+ UINT8 *FileBuffer;
+ UINTN FileBufferSize;
+ EFI_FV_FILETYPE FileType;
+ EFI_FV_FILE_ATTRIBUTES Attrib;
+ UINT32 AuthenticationStatus;
+ UPDATE_CONFIG_DATA *ConfigData;
+ UPDATE_CONFIG_DATA *UpdateConfigData;
+ UINTN NumOfUpdates;
+ UINTN Index;
+ CHAR16 *TmpStr;
+ ESRT_MANAGEMENT_PROTOCOL *EsrtManagement;
+
+
+ ConfigData = NULL;
+ FileBuffer = NULL;
+ AlignedDevPathNode = NULL;
+
+ NewEsrtTemplate.CapsuleFlags = PcdGet16(PcdSystemRebootAfterCapsuleProcessFlag);
+
+ //
+ // Clear screen
+ //
+ //if (gST->ConOut != NULL) {
+ // gST->ConOut->ClearScreen (gST->ConOut);
+ // gST->ConOut->SetAttribute (gST->ConOut, EFI_YELLOW | EFI_BRIGHT);
+ // gST->ConOut->EnableCursor (gST->ConOut, FALSE);
+ //}
+
+ gHiiHandle = HiiAddPackages (
+ &gEfiCallerIdGuid,
+ NULL,
+ UpdateDriverDxeStrings,
+ NULL
+ );
+ if (gHiiHandle == NULL){
+ NewEsrtTemplate.LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL;
+ Status = EFI_OUT_OF_RESOURCES;
+ goto EXIT;
+ }
+
+ //
+ // In order to look for the update data file and programmed image file
+ // from the same volume which this driver is dispatched from, we need
+ // to get the device path of this driver image. It is done by first
+ // locate the LoadedImageProtocol and then get its device path
+ //
+ Status = gBS->OpenProtocol (
+ ImageHandle,
+ &gEfiLoadedImageProtocolGuid,
+ (VOID **)&LoadedImageProtocol,
+ ImageHandle,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ NewEsrtTemplate.LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL;
+ goto EXIT;
+ }
+ //
+ // Get the firmware volume protocol where this file resides
+ //
+ Status = gBS->HandleProtocol (
+ LoadedImageProtocol->DeviceHandle,
+ &gEfiFirmwareVolume2ProtocolGuid,
+ (VOID **) &FwVolProtocol
+ );
+ if (EFI_ERROR (Status)) {
+ NewEsrtTemplate.LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL;
+ goto EXIT;
+ }
+
+ //
+ // Shall do some extra check to see if it is really contained in the FV?
+ // Should be able to find the section of this driver in the the FV.
+ //
+ FilePathNode = LoadedImageProtocol->FilePath;
+ FwVolFilePathNode = NULL;
+ while (!IsDevicePathEnd (FilePathNode)) {
+ if (EfiGetNameGuidFromFwVolDevicePathNode ((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)FilePathNode)!= NULL) {
+ FwVolFilePathNode = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) FilePathNode;
+ break;
+ }
+ FilePathNode = NextDevicePathNode (FilePathNode);
+ }
+
+ if (FwVolFilePathNode == NULL){
+ NewEsrtTemplate.LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL;
+ Status = EFI_NOT_FOUND;
+ goto EXIT;
+ }
+
+ AlignedDevPathNode = AllocateCopyPool (DevicePathNodeLength (FwVolFilePathNode), FwVolFilePathNode);
+
+ SectionType = EFI_SECTION_PE32;
+ FileBuffer = NULL;
+ FileBufferSize = 0;
+ Status = FwVolProtocol->ReadSection (
+ FwVolProtocol,
+ &(AlignedDevPathNode->FvFileName),
+ SectionType,
+ 0,
+ (VOID **) &FileBuffer,
+ &FileBufferSize,
+ &AuthenticationStatus
+ );
+ if (EFI_ERROR (Status)) {
+ NewEsrtTemplate.LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INVALID_FORMAT;
+ goto EXIT;
+ }
+
+ if (FileBuffer != NULL) {
+ FreePool(FileBuffer);
+ FileBuffer = NULL;
+ }
+
+ //
+ // Check the NameGuid of the udpate driver so that it can be
+ // used as the CallerId in fault tolerant write protocol
+ //
+ if (!CompareGuid (&gEfiCallerIdGuid, &(AlignedDevPathNode->FvFileName))) {
+ NewEsrtTemplate.LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INVALID_FORMAT;
+ Status = EFI_NOT_FOUND;
+ goto EXIT;
+ }
+
+ FreePool (AlignedDevPathNode);
+ AlignedDevPathNode = NULL;
+
+
+
+
+ //
+ // Now try to find the script file. The script file is usually
+ // a raw data file which does not contain any sections.
+ //
+ FileBuffer = NULL;
+ FileBufferSize = 0;
+ Status = FwVolProtocol->ReadFile (
+ FwVolProtocol,
+ &gEfiConfigFileNameGuid,
+ (VOID **) &FileBuffer,
+ &FileBufferSize,
+ &FileType,
+ &Attrib,
+ &AuthenticationStatus
+ );
+ if (EFI_ERROR (Status)) {
+ NewEsrtTemplate.LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INVALID_FORMAT;
+ goto EXIT;
+ }
+ if (FileType != EFI_FV_FILETYPE_RAW) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Parse the configuration file.
+ //
+ ConfigData = NULL;
+ NumOfUpdates = 0;
+ Status = ParseUpdateDataFile (
+ FileBuffer,
+ FileBufferSize,
+ &NumOfUpdates,
+ &ConfigData
+ );
+ if (FileBuffer != NULL) {
+ FreePool (FileBuffer);
+ FileBuffer = NULL;
+ }
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ ASSERT (ConfigData != NULL);
+
+ //
+ // Now find the update image. The update image should be put in a FV, and then
+ // encapsulated as a raw FFS file. This is to prevent the update image from
+ // being dispatched. So the raw data we get here should be an FV. We need to
+ // process this FV and read the files that is going to be updated.
+ //
+ FileBuffer = NULL;
+ FileBufferSize = 0;
+ Status = FwVolProtocol->ReadFile (
+ FwVolProtocol,
+ &gEfiUpdateDataFileGuid,
+ (VOID **) &FileBuffer,
+ &FileBufferSize,
+ &FileType,
+ &Attrib,
+ &AuthenticationStatus
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ if (FileType != EFI_FV_FILETYPE_RAW) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // FileBuffer should be an FV. Process the FV
+ //
+ DataFwVolProtocol = NULL;
+ Status = ProcessUpdateImage (
+ FileBuffer,
+ FileBufferSize,
+ &DataFwVolProtocol
+ );
+ if (EFI_ERROR (Status)) {
+ FreePool (FileBuffer);
+ return Status;
+ }
+
+ //
+ // Print on screen
+ //
+ TmpStr = HiiGetString (gHiiHandle, STRING_TOKEN(UPDATE_PROCESS_DATA), NULL);
+ if (TmpStr != NULL) {
+ Print (TmpStr);
+ FreePool(TmpStr);
+ }
+
+ //
+ // Execute the update
+ //
+ Index = 0;
+ UpdateConfigData = ConfigData;
+ while (Index < NumOfUpdates) {
+ Status = PerformUpdate (
+ DataFwVolProtocol,
+ UpdateConfigData
+ );
+ //
+ // Shall updates be serialized so that if an update is not successfully completed,
+ // the remaining updates won't be performed.
+ //
+ if (EFI_ERROR (Status)) {
+ NewEsrtTemplate.LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL;
+ goto EXIT;
+ }
+
+ Index++;
+ UpdateConfigData++;
+ }
+
+
+EXIT:
+
+ //
+ // Sucessfully done update job.
+ // Need to update system firmware Esrt entry
+ //
+ EsrtManagement = NULL;
+ StatusEsrt = gBS->LocateProtocol (&gEsrtManagementProtocolGuid, NULL, (VOID **) &EsrtManagement);
+ if (!EFI_ERROR(StatusEsrt)) {
+ EsrtManagement->UpdateEsrtEntry(&NewEsrtTemplate);
+ }
+
+ //
+ // Do cleanup.
+ //
+ if (gHiiHandle != NULL) {
+ HiiRemovePackages (gHiiHandle);
+ }
+
+ if (AlignedDevPathNode != NULL) {
+ FreePool (AlignedDevPathNode);
+ }
+
+ if (FileBuffer != NULL) {
+ FreePool(FileBuffer);
+ }
+
+ if (ConfigData != NULL) {
+ FreePool(ConfigData);
+ }
+
+ return Status;
+}
diff --git a/Vlv2TbltDevicePkg/UpdateDriverDxe/UpdateDriver.h b/Vlv2TbltDevicePkg/UpdateDriverDxe/UpdateDriver.h
new file mode 100644
index 0000000000..ca0bf9c702
--- /dev/null
+++ b/Vlv2TbltDevicePkg/UpdateDriverDxe/UpdateDriver.h
@@ -0,0 +1,217 @@
+/** @file
+ Common defines and definitions for a component update driver.
+
+ Copyright (c) 2013 - 2015, Intel Corporation. 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 _EFI_UPDATE_DRIVER_H_
+#define _EFI_UPDATE_DRIVER_H_
+
+#include <PiDxe.h>
+
+#include <Guid/Capsule.h>
+#include <Guid/CapsuleDataFile.h>
+#include <Guid/SystemResourceTable.h>
+#include <Guid/SystemFwClassGuid.h>
+
+#include <Protocol/LoadedImage.h>
+#include <Protocol/FaultTolerantWrite.h>
+#include <Protocol/FirmwareVolumeBlock.h>
+#include <Protocol/FirmwareVolume2.h>
+#include <Protocol/EsrtManagement.h>
+
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/HiiLib.h>
+#include <Library/PrintLib.h>
+#include <Library/DevicePathLib.h>
+
+extern EFI_HII_HANDLE gHiiHandle;
+
+typedef enum {
+ UpdateWholeFV = 0, // 0, update whole FV
+ UpdateFvFile, // 1, update a set of FV files asynchronously
+ UpdateFvRange, // 2, update part of FV or flash
+ UpdateOperationMaximum // 3
+} UPDATE_OPERATION_TYPE;
+
+typedef struct {
+ UINTN Index;
+ UPDATE_OPERATION_TYPE UpdateType;
+ EFI_DEVICE_PATH_PROTOCOL DevicePath;
+ EFI_PHYSICAL_ADDRESS BaseAddress;
+ EFI_GUID FileGuid;
+ UINTN Length;
+ BOOLEAN FaultTolerant;
+} UPDATE_CONFIG_DATA;
+
+typedef struct _SECTION_ITEM SECTION_ITEM;
+struct _SECTION_ITEM {
+ CHAR8 *ptrSection;
+ UINTN SecNameLen;
+ CHAR8 *ptrEntry;
+ CHAR8 *ptrValue;
+ SECTION_ITEM *ptrNext;
+};
+
+typedef struct _COMMENT_LINE COMMENT_LINE;
+struct _COMMENT_LINE {
+ CHAR8 *ptrComment;
+ COMMENT_LINE *ptrNext;
+};
+
+typedef struct {
+ EFI_GUID FileGuid;
+} UPDATE_PRIVATE_DATA;
+
+#define MAX_LINE_LENGTH 512
+#define EFI_D_UPDATE EFI_D_ERROR
+
+#define MIN_ALIGNMENT_SIZE 4
+#define ALIGN_SIZE(a) ((a % MIN_ALIGNMENT_SIZE) ? MIN_ALIGNMENT_SIZE - (a % MIN_ALIGNMENT_SIZE) : 0)
+
+/**
+ Parse Config data file to get the updated data array.
+
+ @param DataBuffer Config raw file buffer.
+ @param BufferSize Size of raw buffer.
+ @param NumOfUpdates Pointer to the number of update data.
+ @param UpdateArray Pointer to the config of update data.
+
+ @retval EFI_NOT_FOUND No config data is found.
+ @retval EFI_OUT_OF_RESOURCES No enough memory is allocated.
+ @retval EFI_SUCCESS Parse the config file successfully.
+
+**/
+EFI_STATUS
+ParseUpdateDataFile (
+ IN UINT8 *DataBuffer,
+ IN UINTN BufferSize,
+ IN OUT UINTN *NumOfUpdates,
+ IN OUT UPDATE_CONFIG_DATA **UpdateArray
+ );
+
+/**
+ Update the whole FV image, and reinsall FVB protocol for the updated FV image.
+
+ @param FvbHandle Handle of FVB protocol for the updated flash range.
+ @param FvbProtocol FVB protocol.
+ @param ConfigData Config data on updating driver.
+ @param ImageBuffer Image buffer to be updated.
+ @param ImageSize Image size.
+
+ @retval EFI_INVALID_PARAMETER Update type is not UpdateWholeFV.
+ Or Image size is not same to the size of whole FV.
+ @retval EFI_OUT_OF_RESOURCES No enoug memory is allocated.
+ @retval EFI_SUCCESS FV image is updated, and its FVB protocol is reinstalled.
+
+**/
+EFI_STATUS
+PerformUpdateOnWholeFv (
+ IN EFI_HANDLE FvbHandle,
+ IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvbProtocol,
+ IN UPDATE_CONFIG_DATA *ConfigData,
+ IN UINT8 *ImageBuffer,
+ IN UINTN ImageSize
+ );
+
+/**
+ Update certain file in the FV.
+
+ @param FvbHandle Handle of FVB protocol for the updated flash range.
+ @param FvbProtocol FVB protocol.
+ @param ConfigData Config data on updating driver.
+ @param ImageBuffer Image buffer to be updated.
+ @param ImageSize Image size.
+ @param FileType FFS file type.
+ @param FileAttributes FFS file attribute
+
+ @retval EFI_INVALID_PARAMETER Update type is not UpdateFvFile.
+ Or Image size is not same to the size of whole FV.
+ @retval EFI_UNSUPPORTED PEIM FFS is unsupported to be updated.
+ @retval EFI_SUCCESS The FFS file is added into FV.
+
+**/
+EFI_STATUS
+PerformUpdateOnFvFile (
+ IN EFI_HANDLE FvbHandle,
+ IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvbProtocol,
+ IN UPDATE_CONFIG_DATA *ConfigData,
+ IN UINT8 *ImageBuffer,
+ IN UINTN ImageSize,
+ IN EFI_FV_FILETYPE FileType,
+ IN EFI_FV_FILE_ATTRIBUTES FileAttributes
+ );
+
+/**
+ Update the buffer into flash area in fault tolerant write method.
+
+ @param ImageBuffer Image buffer to be updated.
+ @param SizeLeft Size of the image buffer.
+ @param UpdatedSize Size of the updated buffer.
+ @param ConfigData Config data on updating driver.
+ @param FlashAddress Flash address to be updated as start address.
+ @param FvbProtocol FVB protocol.
+ @param FvbHandle Handle of FVB protocol for the updated flash range.
+
+ @retval EFI_SUCCESS Buffer data is updated into flash.
+ @retval EFI_INVALID_PARAMETER Base flash address is not in FVB flash area.
+ @retval EFI_NOT_FOUND FTW protocol doesn't exist.
+ @retval EFI_OUT_OF_RESOURCES No enough backup space.
+ @retval EFI_ABORTED Error happen when update flash area.
+
+**/
+EFI_STATUS
+FaultTolerantUpdateOnPartFv (
+ IN UINT8 *ImageBuffer,
+ IN UINTN SizeLeft,
+ IN OUT UINTN *UpdatedSize,
+ IN UPDATE_CONFIG_DATA *ConfigData,
+ IN EFI_PHYSICAL_ADDRESS FlashAddress,
+ IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvbProtocol,
+ IN EFI_HANDLE FvbHandle
+ );
+
+/**
+ Directly update the buffer into flash area without fault tolerant write method.
+
+ @param ImageBuffer Image buffer to be updated.
+ @param SizeLeft Size of the image buffer.
+ @param UpdatedSize Size of the updated buffer.
+ @param FlashAddress Flash address to be updated as start address.
+ @param FvbProtocol FVB protocol.
+ @param FvbHandle Handle of FVB protocol for the updated flash range.
+
+ @retval EFI_SUCCESS Buffer data is updated into flash.
+ @retval EFI_INVALID_PARAMETER Base flash address is not in FVB flash area.
+ @retval EFI_OUT_OF_RESOURCES No enough backup space.
+
+**/
+EFI_STATUS
+NonFaultTolerantUpdateOnPartFv (
+ IN UINT8 *ImageBuffer,
+ IN UINTN SizeLeft,
+ IN OUT UINTN *UpdatedSize,
+ IN EFI_PHYSICAL_ADDRESS FlashAddress,
+ IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvbProtocol,
+ IN EFI_HANDLE FvbHandle
+ );
+
+#endif
diff --git a/Vlv2TbltDevicePkg/UpdateDriverDxe/UpdateDriverDxe.inf b/Vlv2TbltDevicePkg/UpdateDriverDxe/UpdateDriverDxe.inf
new file mode 100644
index 0000000000..8ecce74596
--- /dev/null
+++ b/Vlv2TbltDevicePkg/UpdateDriverDxe/UpdateDriverDxe.inf
@@ -0,0 +1,82 @@
+## @file
+# Update Driver for Capulse update.
+#
+# This driver is intended to be put in a capsule (FV). If all goes well,
+# then it should be dispatched from the capsule FV, then find the image
+# in the same FV and program it in a target Firmware Volume device.
+#
+# Copyright (c) 2004 - 2016, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# 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 = UpdateDriverDxe
+ MODULE_UNI_FILE = UpdateDriverDxe.uni
+ FILE_GUID = 0E84FC69-29CC-4C6D-92AC-6D476921850F
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = InitializeUpdateDriver
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources]
+ UpdateDriver.h
+ UpdateStrings.uni
+ UpdateDispatcher.c
+ ParseUpdateProfile.c
+ FlashUpdate.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ IntelFrameworkPkg/IntelFrameworkPkg.dec
+ IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec
+ Vlv2TbltDevicePkg/PlatformPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ PrintLib
+ HiiLib
+ DxeServicesTableLib
+ MemoryAllocationLib
+ UefiLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+ UefiRuntimeServicesTableLib
+ BaseMemoryLib
+ DebugLib
+ DevicePathLib
+ PcdLib
+
+[Pcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdSystemRebootAfterCapsuleProcessFlag ## CONSUMES
+
+[Guids]
+ gEfiConfigFileNameGuid ## CONSUMES ## File # FileName to store ConfigFile
+ gEfiUpdateDataFileGuid ## CONSUMES ## File # FileName to store Capsule Data.
+ gSystemFwClassGuid ## CONSUMES
+
+[Protocols]
+ gEfiFaultTolerantWriteProtocolGuid ## CONSUMES
+ gEfiFirmwareVolume2ProtocolGuid ## CONSUMES
+ gEfiFirmwareVolumeBlockProtocolGuid ## CONSUMES
+ gEfiLoadedImageProtocolGuid ## CONSUMES
+ gEsrtManagementProtocolGuid ## SOMETIMES_CONSUME
+
+[Depex]
+ gEfiFirmwareVolumeBlockProtocolGuid AND gEfiFaultTolerantWriteProtocolGuid
+
diff --git a/Vlv2TbltDevicePkg/UpdateDriverDxe/UpdateDriverDxe.uni b/Vlv2TbltDevicePkg/UpdateDriverDxe/UpdateDriverDxe.uni
new file mode 100644
index 0000000000..d020e42ab2
--- /dev/null
+++ b/Vlv2TbltDevicePkg/UpdateDriverDxe/UpdateDriverDxe.uni
Binary files differ
diff --git a/Vlv2TbltDevicePkg/UpdateDriverDxe/UpdateStrings.uni b/Vlv2TbltDevicePkg/UpdateDriverDxe/UpdateStrings.uni
new file mode 100644
index 0000000000..84e73c2386
--- /dev/null
+++ b/Vlv2TbltDevicePkg/UpdateDriverDxe/UpdateStrings.uni
Binary files differ