4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/** @file
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BDS routines to handle capsules.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncCopyright (c) 2004 - 2011, Intel Corporation. All rights reserved.<BR>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncThis program and the accompanying materials
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncare licensed and made available under the terms and conditions of the BSD License
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncwhich accompanies this distribution. The full text of the license may be found at
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsynchttp://opensource.org/licenses/bsd-license.php
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncTHE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncWITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include "Bds.h"
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync This routine is called to see if there are any capsules we need to process.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync If the boot mode is not UPDATE, then we do nothing. Otherwise find the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync capsule HOBS and produce firmware volumes for them via the DXE service.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Then call the dispatcher to dispatch drivers from them. Finally, check
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync the status of the updates.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync This function should be called by BDS in case we need to do some
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync sort of processing even if there is no capsule to process. We
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync need to do this if an earlier update went away and we need to
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync clear the capsule variable so on the next reset PEI does not see it and
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync think there is a capsule available.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param BootMode the current boot mode
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_INVALID_PARAMETER boot mode is not correct for an update
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SUCCESS There is no error when processing capsule
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFI_STATUS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFIAPI
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncBdsProcessCapsules (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_BOOT_MODE BootMode
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_STATUS Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_PEI_HOB_POINTERS HobPointer;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_CAPSULE_HEADER *CapsuleHeader;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT32 Size;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT32 CapsuleNumber;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT32 CapsuleTotalNumber;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_CAPSULE_TABLE *CapsuleTable;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT32 Index;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT32 CacheIndex;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT32 CacheNumber;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VOID **CapsulePtr;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VOID **CapsulePtrCache;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_GUID *CapsuleGuidCache;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CapsuleNumber = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CapsuleTotalNumber = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CacheIndex = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CacheNumber = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CapsulePtr = NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CapsulePtrCache = NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CapsuleGuidCache = NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // We don't do anything else if the boot mode is not flash-update
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (BootMode != BOOT_ON_FLASH_UPDATE) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DEBUG ((EFI_D_ERROR, "Boot mode is not correct for capsule update.\n"));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_INVALID_PARAMETER;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = EFI_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Find all capsule images from hob
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync HobPointer.Raw = GetHobList ();
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync while ((HobPointer.Raw = GetNextHob (EFI_HOB_TYPE_UEFI_CAPSULE, HobPointer.Raw)) != NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CapsuleTotalNumber ++;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync HobPointer.Raw = GET_NEXT_HOB (HobPointer);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (CapsuleTotalNumber == 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // We didn't find a hob, so had no errors.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DEBUG ((EFI_D_ERROR, "We can not find capsule data in capsule update boot mode.\n"));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DEBUG ((EFI_D_ERROR, "Please check the followings are correct if unexpected capsule update error happens.\n"));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DEBUG ((EFI_D_ERROR, "1. CapsuleX64 is built as X64 module when PEI is IA32 and DXE is X64\n"));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DEBUG ((EFI_D_ERROR, "2. Capsule data should persist in memory across a system reset.\n"));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PlatformBdsLockNonUpdatableFlash ();
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Init temp Capsule Data table.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CapsulePtr = (VOID **) AllocateZeroPool (sizeof (VOID *) * CapsuleTotalNumber);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (CapsulePtr != NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CapsulePtrCache = (VOID **) AllocateZeroPool (sizeof (VOID *) * CapsuleTotalNumber);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (CapsulePtrCache != NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CapsuleGuidCache = (EFI_GUID *) AllocateZeroPool (sizeof (EFI_GUID) * CapsuleTotalNumber);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (CapsuleGuidCache != NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Find all capsule images from hob
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync HobPointer.Raw = GetHobList ();
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync while ((HobPointer.Raw = GetNextHob (EFI_HOB_TYPE_UEFI_CAPSULE, HobPointer.Raw)) != NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CapsulePtr [CapsuleNumber++] = (VOID *) (UINTN) HobPointer.Capsule->BaseAddress;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync HobPointer.Raw = GET_NEXT_HOB (HobPointer);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //Check the capsule flags,if contains CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE, install
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //capsuleTable to configure table with EFI_CAPSULE_GUID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Capsules who have CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE always are used for operating
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // System to have information persist across a system reset. EFI System Table must
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // point to an array of capsules that contains the same CapsuleGuid value. And agents
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // searching for this type capsule will look in EFI System Table and search for the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // capsule's Guid and associated pointer to retrieve the data. Two steps below describes
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // how to sorting the capsules by the unique guid and install the array to EFI System Table.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Firstly, Loop for all coalesced capsules, record unique CapsuleGuids and cache them in an
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // array for later sorting capsules by CapsuleGuid.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for (Index = 0; Index < CapsuleTotalNumber; Index++) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CapsuleHeader = (EFI_CAPSULE_HEADER*) CapsulePtr [Index];
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) != 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // For each capsule, we compare it with known CapsuleGuid in the CacheArray.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // If already has the Guid, skip it. Whereas, record it in the CacheArray as
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // an additional one.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CacheIndex = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync while (CacheIndex < CacheNumber) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (CompareGuid(&CapsuleGuidCache[CacheIndex],&CapsuleHeader->CapsuleGuid)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CacheIndex++;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (CacheIndex == CacheNumber) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CopyMem(&CapsuleGuidCache[CacheNumber++],&CapsuleHeader->CapsuleGuid,sizeof(EFI_GUID));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Secondly, for each unique CapsuleGuid in CacheArray, gather all coalesced capsules
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // whose guid is the same as it, and malloc memory for an array which preceding
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // with UINT32. The array fills with entry point of capsules that have the same
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // CapsuleGuid, and UINT32 represents the size of the array of capsules. Then install
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // this array into EFI System Table, so that agents searching for this type capsule
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // will look in EFI System Table and search for the capsule's Guid and associated
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // pointer to retrieve the data.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CacheIndex = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync while (CacheIndex < CacheNumber) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CapsuleNumber = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for (Index = 0; Index < CapsuleTotalNumber; Index++) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CapsuleHeader = (EFI_CAPSULE_HEADER*) CapsulePtr [Index];
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) != 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (CompareGuid (&CapsuleGuidCache[CacheIndex], &CapsuleHeader->CapsuleGuid)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Cache Caspuleheader to the array, this array is uniqued with certain CapsuleGuid.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CapsulePtrCache[CapsuleNumber++] = (VOID*)CapsuleHeader;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (CapsuleNumber != 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Size = sizeof(EFI_CAPSULE_TABLE) + (CapsuleNumber - 1) * sizeof(VOID*);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CapsuleTable = AllocateRuntimePool (Size);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (CapsuleTable != NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CapsuleTable->CapsuleArrayNumber = CapsuleNumber;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CopyMem(&CapsuleTable->CapsulePtr[0], CapsulePtrCache, CapsuleNumber * sizeof(VOID*));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = gBS->InstallConfigurationTable (&CapsuleGuidCache[CacheIndex], (VOID*)CapsuleTable);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT_EFI_ERROR (Status);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CacheIndex++;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Besides ones with CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE flag, all capsules left are
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // recognized by platform with CapsuleGuid. For general platform driver, UpdateFlash
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // type is commonly supported, so here only deal with encapsuled FVs capsule. Additional
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // type capsule transaction could be extended. It depends on platform policy.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for (Index = 0; Index < CapsuleTotalNumber; Index++) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CapsuleHeader = (EFI_CAPSULE_HEADER*) CapsulePtr [Index];
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) == 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Call capsule library to process capsule image.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ProcessCapsuleImage (CapsuleHeader);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PlatformBdsLockNonUpdatableFlash ();
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Free the allocated temp memory space.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FreePool (CapsuleGuidCache);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FreePool (CapsulePtrCache);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FreePool (CapsulePtr);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync