-/*++\r
+/** @file\r
+ Capsule Runtime Driver produces two UEFI capsule runtime services.\r
+ (UpdateCapsule, QueryCapsuleCapabilities)\r
+ It installs the Capsule Architectural Protocol defined in PI1.0a to signify\r
+ the capsule runtime services are ready.\r
\r
-Copyright (c) 2006 - 2007, Intel Corporation\r
-All rights reserved. This program and the accompanying materials\r
-are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution. The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php\r
+Copyright (c) 2006 - 2020, Intel Corporation. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-\r
-Module Name:\r
-\r
- CapsuleService.c\r
-\r
-Abstract:\r
-\r
- Capsule Runtime Service.\r
-\r
---*/\r
+**/\r
\r
#include "CapsuleService.h"\r
\r
+//\r
+// Handle for the installation of Capsule Architecture Protocol.\r
+//\r
+EFI_HANDLE mNewHandle = NULL;\r
+\r
+//\r
+// The times of calling UpdateCapsule ()\r
+//\r
+UINTN mTimes = 0;\r
+\r
+UINT32 mMaxSizePopulateCapsule = 0;\r
+UINT32 mMaxSizeNonPopulateCapsule = 0;\r
+\r
+/**\r
+ Passes capsules to the firmware with both virtual and physical mapping. Depending on the intended\r
+ consumption, the firmware may process the capsule immediately. If the payload should persist\r
+ across a system reset, the reset value returned from EFI_QueryCapsuleCapabilities must\r
+ be passed into ResetSystem() and will cause the capsule to be processed by the firmware as\r
+ part of the reset process.\r
+\r
+ @param CapsuleHeaderArray Virtual pointer to an array of virtual pointers to the capsules\r
+ being passed into update capsule.\r
+ @param CapsuleCount Number of pointers to EFI_CAPSULE_HEADER in\r
+ CaspuleHeaderArray.\r
+ @param ScatterGatherList Physical pointer to a set of\r
+ EFI_CAPSULE_BLOCK_DESCRIPTOR that describes the\r
+ location in physical memory of a set of capsules.\r
+\r
+ @retval EFI_SUCCESS Valid capsule was passed. If\r
+ CAPSULE_FLAGS_PERSIT_ACROSS_RESET is not set, the\r
+ capsule has been successfully processed by the firmware.\r
+ @retval EFI_DEVICE_ERROR The capsule update was started, but failed due to a device error.\r
+ @retval EFI_INVALID_PARAMETER CapsuleSize is NULL, or an incompatible set of flags were\r
+ set in the capsule header.\r
+ @retval EFI_INVALID_PARAMETER CapsuleCount is Zero.\r
+ @retval EFI_INVALID_PARAMETER For across reset capsule image, ScatterGatherList is NULL.\r
+ @retval EFI_UNSUPPORTED CapsuleImage is not recognized by the firmware.\r
+ @retval EFI_OUT_OF_RESOURCES When ExitBootServices() has been previously called this error indicates the capsule\r
+ is compatible with this platform but is not capable of being submitted or processed\r
+ in runtime. The caller may resubmit the capsule prior to ExitBootServices().\r
+ @retval EFI_OUT_OF_RESOURCES When ExitBootServices() has not been previously called then this error indicates\r
+ the capsule is compatible with this platform but there are insufficient resources to process.\r
+\r
+**/\r
EFI_STATUS\r
EFIAPI\r
UpdateCapsule (\r
- IN EFI_CAPSULE_HEADER **CapsuleHeaderArray,\r
- IN UINTN CapsuleCount,\r
- IN EFI_PHYSICAL_ADDRESS ScatterGatherList OPTIONAL\r
+ IN EFI_CAPSULE_HEADER **CapsuleHeaderArray,\r
+ IN UINTN CapsuleCount,\r
+ IN EFI_PHYSICAL_ADDRESS ScatterGatherList OPTIONAL\r
)\r
-/*++\r
-\r
-Routine Description:\r
-\r
- This code finds whether the capsules need reset to update, if not, update immediately.\r
-\r
-Arguments:\r
-\r
- CapsuleHeaderArray A array of pointers to capsule headers passed in\r
- CapsuleCount The number of capsule\r
- ScatterGatherList Physical address of datablock list points to capsule\r
-\r
-Returns:\r
-\r
- EFI STATUS\r
- EFI_SUCCESS Valid capsule was passed.If CAPSULE_FLAG_PERSIT_ACROSS_RESET is\r
- not set, the capsule has been successfully processed by the firmware.\r
- If it set, the ScattlerGatherList is successfully to be set.\r
- EFI_INVALID_PARAMETER CapsuleCount is less than 1,CapsuleGuid is not supported.\r
- EFI_DEVICE_ERROR Failed to SetVariable or ProcessFirmwareVolume.\r
-\r
---*/\r
{\r
- UINTN ArrayNumber;\r
- EFI_STATUS Status;\r
- EFI_CAPSULE_HEADER *CapsuleHeader;\r
+ UINTN ArrayNumber;\r
+ EFI_STATUS Status;\r
+ EFI_CAPSULE_HEADER *CapsuleHeader;\r
+ BOOLEAN NeedReset;\r
+ BOOLEAN InitiateReset;\r
+ CHAR16 CapsuleVarName[30];\r
+ CHAR16 *TempVarName;\r
\r
+ //\r
+ // Check if platform support Capsule In RAM or not.\r
+ // Platform could choose to drop CapsulePei/CapsuleX64 and do not support Capsule In RAM.\r
+ //\r
+ if (!PcdGetBool (PcdCapsuleInRamSupport)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ //\r
+ // Capsule Count can't be less than one.\r
+ //\r
if (CapsuleCount < 1) {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
- CapsuleHeader = NULL;\r
+ NeedReset = FALSE;\r
+ InitiateReset = FALSE;\r
+ CapsuleHeader = NULL;\r
+ CapsuleVarName[0] = 0;\r
\r
for (ArrayNumber = 0; ArrayNumber < CapsuleCount; ArrayNumber++) {\r
//\r
if ((CapsuleHeader->Flags & (CAPSULE_FLAGS_PERSIST_ACROSS_RESET | CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE)) == CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) {\r
return EFI_INVALID_PARAMETER;\r
}\r
+\r
//\r
- // Check Capsule image without populate flag by firmware support capsule function \r
+ // A capsule which has the CAPSULE_FLAGS_INITIATE_RESET flag must have\r
+ // CAPSULE_FLAGS_PERSIST_ACROSS_RESET set in its header as well.\r
//\r
- if (((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) == 0) && \r
- (SupportCapsuleImage (CapsuleHeader) != EFI_SUCCESS)) {\r
- return EFI_UNSUPPORTED;\r
+ if ((CapsuleHeader->Flags & (CAPSULE_FLAGS_PERSIST_ACROSS_RESET | CAPSULE_FLAGS_INITIATE_RESET)) == CAPSULE_FLAGS_INITIATE_RESET) {\r
+ return EFI_INVALID_PARAMETER;\r
}\r
- }\r
\r
- //\r
- // Assume that capsules have the same flags on reseting or not.\r
- //\r
- CapsuleHeader = CapsuleHeaderArray[0];\r
+ //\r
+ // Check FMP capsule flag\r
+ //\r
+ if ( CompareGuid (&CapsuleHeader->CapsuleGuid, &gEfiFmpCapsuleGuid)\r
+ && ((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) != 0))\r
+ {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
\r
- if ((CapsuleHeader->Flags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET) != 0) {\r
//\r
- // Check if the platform supports update capsule across a system reset\r
+ // Check Capsule image without populate flag by firmware support capsule function\r
//\r
- if (!FeaturePcdGet(PcdSupportUpdateCapsuleRest)) {\r
- return EFI_UNSUPPORTED;\r
+ if ((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) == 0) {\r
+ Status = SupportCapsuleImage (CapsuleHeader);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
}\r
+ }\r
+\r
+ //\r
+ // Walk through all capsules, record whether there is a capsule needs reset\r
+ // or initiate reset. And then process capsules which has no reset flag directly.\r
+ //\r
+ for (ArrayNumber = 0; ArrayNumber < CapsuleCount; ArrayNumber++) {\r
+ CapsuleHeader = CapsuleHeaderArray[ArrayNumber];\r
//\r
- // ScatterGatherList is only referenced if the capsules are defined to persist across\r
- // system reset. \r
+ // Here should be in the boot-time for non-reset capsule image\r
+ // Platform specific update for the non-reset capsule image.\r
//\r
- if (ScatterGatherList == (EFI_PHYSICAL_ADDRESS) (UINTN) NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- } else {\r
- //\r
- // ScatterGatherList is only referenced if the capsules are defined to persist across\r
- // system reset. Set its value into NV storage to let pre-boot driver to pick it up \r
- // after coming through a system reset.\r
- //\r
- Status = EfiSetVariable (\r
- EFI_CAPSULE_VARIABLE_NAME,\r
- &gEfiCapsuleVendorGuid,\r
- EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
- sizeof (UINTN),\r
- (VOID *) &ScatterGatherList\r
- );\r
- if (Status != EFI_SUCCESS) {\r
+ if ((CapsuleHeader->Flags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET) == 0) {\r
+ if (EfiAtRuntime () && !FeaturePcdGet (PcdSupportProcessCapsuleAtRuntime)) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ } else {\r
+ Status = ProcessCapsuleImage (CapsuleHeader);\r
+ }\r
+\r
+ if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
- //\r
- // Successfully set the capsule image address into variable.\r
- //\r
- return EFI_SUCCESS;\r
+ } else {\r
+ NeedReset = TRUE;\r
+ if ((CapsuleHeader->Flags & CAPSULE_FLAGS_INITIATE_RESET) != 0) {\r
+ InitiateReset = TRUE;\r
+ }\r
}\r
}\r
\r
//\r
- // The rest occurs in the condition of non-reset mode\r
- // Now Runtime mode doesn't support the non-reset capsule image.\r
+ // After launching all capsules who has no reset flag, if no more capsules claims\r
+ // for a system reset just return.\r
+ //\r
+ if (!NeedReset) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ //\r
+ // ScatterGatherList is only referenced if the capsules are defined to persist across\r
+ // system reset.\r
//\r
- if (EfiAtRuntime ()) {\r
+ if (ScatterGatherList == (EFI_PHYSICAL_ADDRESS)(UINTN)NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Check if the platform supports update capsule across a system reset\r
+ //\r
+ if (!IsPersistAcrossResetCapsuleSupported ()) {\r
return EFI_UNSUPPORTED;\r
}\r
\r
+ CapsuleCacheWriteBack (ScatterGatherList);\r
+\r
//\r
- // Here should be in the boot-time for non-reset capsule image\r
- // Default process to Update Capsule image into Flash.\r
+ // Construct variable name CapsuleUpdateData, CapsuleUpdateData1, CapsuleUpdateData2...\r
+ // if user calls UpdateCapsule multiple times.\r
//\r
- for (ArrayNumber = 0; ArrayNumber < CapsuleCount ; ArrayNumber++) {\r
- Status = ProcessCapsuleImage (CapsuleHeaderArray[ArrayNumber]);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
+ StrCpyS (CapsuleVarName, sizeof (CapsuleVarName)/sizeof (CHAR16), EFI_CAPSULE_VARIABLE_NAME);\r
+ TempVarName = CapsuleVarName + StrLen (CapsuleVarName);\r
+ if (mTimes > 0) {\r
+ UnicodeValueToStringS (\r
+ TempVarName,\r
+ sizeof (CapsuleVarName) - ((UINTN)TempVarName - (UINTN)CapsuleVarName),\r
+ 0,\r
+ mTimes,\r
+ 0\r
+ );\r
+ }\r
+\r
+ //\r
+ // ScatterGatherList is only referenced if the capsules are defined to persist across\r
+ // system reset. Set its value into NV storage to let pre-boot driver to pick it up\r
+ // after coming through a system reset.\r
+ //\r
+ Status = EfiSetVariable (\r
+ CapsuleVarName,\r
+ &gEfiCapsuleVendorGuid,\r
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
+ sizeof (UINTN),\r
+ (VOID *)&ScatterGatherList\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // Variable has been set successfully, increase variable index.\r
+ //\r
+ mTimes++;\r
+ if (InitiateReset) {\r
+ //\r
+ // Firmware that encounters a capsule which has the CAPSULE_FLAGS_INITIATE_RESET Flag set in its header\r
+ // will initiate a reset of the platform which is compatible with the passed-in capsule request and will\r
+ // not return back to the caller.\r
+ //\r
+ EfiResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);\r
}\r
}\r
\r
- return EFI_SUCCESS;\r
+ return Status;\r
}\r
\r
-\r
-\r
+/**\r
+ Returns if the capsule can be supported via UpdateCapsule().\r
+ Notice: When PcdCapsuleInRamSupport is unsupported, even this routine returns a valid answer,\r
+ the capsule still is unsupported via UpdateCapsule().\r
+\r
+ @param CapsuleHeaderArray Virtual pointer to an array of virtual pointers to the capsules\r
+ being passed into update capsule.\r
+ @param CapsuleCount Number of pointers to EFI_CAPSULE_HEADER in\r
+ CaspuleHeaderArray.\r
+ @param MaxiumCapsuleSize On output the maximum size that UpdateCapsule() can\r
+ support as an argument to UpdateCapsule() via\r
+ CapsuleHeaderArray and ScatterGatherList.\r
+ @param ResetType Returns the type of reset required for the capsule update.\r
+\r
+ @retval EFI_SUCCESS Valid answer returned.\r
+ @retval EFI_UNSUPPORTED The capsule image is not supported on this platform, and\r
+ MaximumCapsuleSize and ResetType are undefined.\r
+ @retval EFI_INVALID_PARAMETER MaximumCapsuleSize is NULL, or ResetTyep is NULL,\r
+ Or CapsuleCount is Zero, or CapsuleImage is not valid.\r
+\r
+**/\r
EFI_STATUS\r
EFIAPI\r
QueryCapsuleCapabilities (\r
- IN EFI_CAPSULE_HEADER **CapsuleHeaderArray,\r
- IN UINTN CapsuleCount,\r
- OUT UINT64 *MaxiumCapsuleSize,\r
- OUT EFI_RESET_TYPE *ResetType\r
+ IN EFI_CAPSULE_HEADER **CapsuleHeaderArray,\r
+ IN UINTN CapsuleCount,\r
+ OUT UINT64 *MaxiumCapsuleSize,\r
+ OUT EFI_RESET_TYPE *ResetType\r
)\r
-/*++\r
-\r
-Routine Description:\r
-\r
- This code is to query about capsule capability.\r
-\r
-Arguments:\r
-\r
- CapsuleHeaderArray A array of pointers to capsule headers passed in\r
- CapsuleCount The number of capsule\r
- MaxiumCapsuleSize Max capsule size is supported\r
- ResetType Reset type the capsule indicates, if reset is not needed,return EfiResetCold.\r
- If reset is needed, return EfiResetWarm.\r
-\r
-Returns:\r
-\r
- EFI STATUS\r
- EFI_SUCCESS Valid answer returned\r
- EFI_INVALID_PARAMETER MaxiumCapsuleSize is NULL,ResetType is NULL.CapsuleCount is less than 1,CapsuleGuid is not supported.\r
- EFI_UNSUPPORTED The capsule type is not supported.\r
-\r
---*/\r
{\r
- UINTN ArrayNumber;\r
- EFI_CAPSULE_HEADER *CapsuleHeader;\r
+ EFI_STATUS Status;\r
+ UINTN ArrayNumber;\r
+ EFI_CAPSULE_HEADER *CapsuleHeader;\r
+ BOOLEAN NeedReset;\r
\r
+ //\r
+ // Capsule Count can't be less than one.\r
+ //\r
if (CapsuleCount < 1) {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
- if ((MaxiumCapsuleSize == NULL) ||(ResetType == NULL)) {\r
+ //\r
+ // Check whether input parameter is valid\r
+ //\r
+ if ((MaxiumCapsuleSize == NULL) || (ResetType == NULL)) {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
CapsuleHeader = NULL;\r
+ NeedReset = FALSE;\r
\r
for (ArrayNumber = 0; ArrayNumber < CapsuleCount; ArrayNumber++) {\r
CapsuleHeader = CapsuleHeaderArray[ArrayNumber];\r
if ((CapsuleHeader->Flags & (CAPSULE_FLAGS_PERSIST_ACROSS_RESET | CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE)) == CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) {\r
return EFI_INVALID_PARAMETER;\r
}\r
+\r
//\r
- // Check Capsule image without populate flag by firmware support capsule function \r
+ // A capsule which has the CAPSULE_FLAGS_INITIATE_RESET flag must have\r
+ // CAPSULE_FLAGS_PERSIST_ACROSS_RESET set in its header as well.\r
//\r
- if (((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) == 0) && \r
- (SupportCapsuleImage (CapsuleHeader) != EFI_SUCCESS)) {\r
- return EFI_UNSUPPORTED;\r
+ if ((CapsuleHeader->Flags & (CAPSULE_FLAGS_PERSIST_ACROSS_RESET | CAPSULE_FLAGS_INITIATE_RESET)) == CAPSULE_FLAGS_INITIATE_RESET) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Check FMP capsule flag\r
+ //\r
+ if ( CompareGuid (&CapsuleHeader->CapsuleGuid, &gEfiFmpCapsuleGuid)\r
+ && ((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) != 0))\r
+ {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Check Capsule image without populate flag is supported by firmware\r
+ //\r
+ if ((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) == 0) {\r
+ Status = SupportCapsuleImage (CapsuleHeader);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
}\r
}\r
\r
//\r
- //Assume that capsules have the same flags on reseting or not.\r
+ // Find out whether there is any capsule defined to persist across system reset.\r
//\r
- CapsuleHeader = CapsuleHeaderArray[0];\r
- if ((CapsuleHeader->Flags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET) != 0) {\r
+ for (ArrayNumber = 0; ArrayNumber < CapsuleCount; ArrayNumber++) {\r
+ CapsuleHeader = CapsuleHeaderArray[ArrayNumber];\r
+ if ((CapsuleHeader->Flags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET) != 0) {\r
+ NeedReset = TRUE;\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (NeedReset) {\r
//\r
- //Check if the platform supports update capsule across a system reset\r
+ // Check if the platform supports update capsule across a system reset\r
//\r
- if (!FeaturePcdGet(PcdSupportUpdateCapsuleRest)) {\r
+ if (!IsPersistAcrossResetCapsuleSupported ()) {\r
return EFI_UNSUPPORTED;\r
}\r
- *ResetType = EfiResetWarm;\r
- *MaxiumCapsuleSize = FixedPcdGet32(PcdMaxSizePopulateCapsule);\r
+\r
+ *ResetType = EfiResetWarm;\r
+ *MaxiumCapsuleSize = (UINT64)mMaxSizePopulateCapsule;\r
} else {\r
- *ResetType = EfiResetCold;\r
- *MaxiumCapsuleSize = FixedPcdGet32(PcdMaxSizeNonPopulateCapsule);\r
+ //\r
+ // For non-reset capsule image.\r
+ //\r
+ *ResetType = EfiResetCold;\r
+ *MaxiumCapsuleSize = (UINT64)mMaxSizeNonPopulateCapsule;\r
}\r
+\r
return EFI_SUCCESS;\r
}\r
\r
+/**\r
+\r
+ This code installs UEFI capsule runtime service.\r
\r
+ @param ImageHandle The firmware allocated handle for the EFI image.\r
+ @param SystemTable A pointer to the EFI System Table.\r
+\r
+ @retval EFI_SUCCESS UEFI Capsule Runtime Services are installed successfully.\r
+\r
+**/\r
EFI_STATUS\r
EFIAPI\r
CapsuleServiceInitialize (\r
- IN EFI_HANDLE ImageHandle,\r
- IN EFI_SYSTEM_TABLE *SystemTable\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
)\r
-/*++\r
-\r
-Routine Description:\r
-\r
- This code is capsule runtime service initialization.\r
-\r
-Arguments:\r
-\r
- ImageHandle The image handle\r
- SystemTable The system table.\r
-\r
-Returns:\r
-\r
- EFI STATUS\r
-\r
---*/\r
{\r
EFI_STATUS Status;\r
- EFI_HANDLE NewHandle;\r
\r
- SystemTable->RuntimeServices->UpdateCapsule = UpdateCapsule;\r
- SystemTable->RuntimeServices->QueryCapsuleCapabilities = QueryCapsuleCapabilities;\r
+ mMaxSizePopulateCapsule = PcdGet32 (PcdMaxSizePopulateCapsule);\r
+ mMaxSizeNonPopulateCapsule = PcdGet32 (PcdMaxSizeNonPopulateCapsule);\r
+\r
+ //\r
+ // When PEI phase is IA32, DXE phase is X64, it is possible that capsule data are\r
+ // put above 4GB, so capsule PEI will transfer to long mode to get capsule data.\r
+ // The page table and stack is used to transfer processor mode from IA32 to long mode.\r
+ // Create the base address of page table and stack, and save them into variable.\r
+ // This is not needed when capsule with reset type is not supported.\r
+ //\r
+ SaveLongModeContext ();\r
\r
//\r
- // Now install the Capsule Architectural Protocol on a new handle\r
+ // Install capsule runtime services into UEFI runtime service tables.\r
//\r
- NewHandle = NULL;\r
+ gRT->UpdateCapsule = UpdateCapsule;\r
+ gRT->QueryCapsuleCapabilities = QueryCapsuleCapabilities;\r
\r
+ //\r
+ // Install the Capsule Architectural Protocol on a new handle\r
+ // to signify the capsule runtime services are ready.\r
+ //\r
Status = gBS->InstallMultipleProtocolInterfaces (\r
- &NewHandle,\r
+ &mNewHandle,\r
&gEfiCapsuleArchProtocolGuid,\r
NULL,\r
NULL\r
);\r
ASSERT_EFI_ERROR (Status);\r
\r
- return EFI_SUCCESS;\r
+ return Status;\r
}\r