summaryrefslogtreecommitdiff
path: root/EdkModulePkg/Universal/Capsule/RuntimeDxe/CapsuleService.c
diff options
context:
space:
mode:
Diffstat (limited to 'EdkModulePkg/Universal/Capsule/RuntimeDxe/CapsuleService.c')
-rw-r--r--EdkModulePkg/Universal/Capsule/RuntimeDxe/CapsuleService.c238
1 files changed, 238 insertions, 0 deletions
diff --git a/EdkModulePkg/Universal/Capsule/RuntimeDxe/CapsuleService.c b/EdkModulePkg/Universal/Capsule/RuntimeDxe/CapsuleService.c
new file mode 100644
index 0000000..e07cbc8
--- /dev/null
+++ b/EdkModulePkg/Universal/Capsule/RuntimeDxe/CapsuleService.c
@@ -0,0 +1,238 @@
+/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. 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.
+
+Module Name:
+
+ CapsuleService.c
+
+Abstract:
+
+ Capsule Runtime Service.
+
+--*/
+
+#include "CapsuleService.h"
+
+
+STATIC EFI_GUID mEfiCapsuleHeaderGuid = EFI_CAPSULE_GUID;
+
+
+EFI_STATUS
+EFIAPI
+UpdateCapsule (
+ IN UEFI_CAPSULE_HEADER **CapsuleHeaderArray,
+ IN UINTN CapsuleCount,
+ IN EFI_PHYSICAL_ADDRESS ScatterGatherList OPTIONAL
+ )
+/*++
+
+Routine Description:
+
+ This code finds whether the capsules need reset to update, if not, update immediately.
+
+Arguments:
+
+ CapsuleHeaderArray A array of pointers to capsule headers passed in
+ CapsuleCount The number of capsule
+ ScatterGatherList Physical address of datablock list points to capsule
+
+Returns:
+
+ EFI STATUS
+ EFI_SUCCESS Valid capsule was passed.If CAPSULE_FLAG_PERSIT_ACROSS_RESET is
+ not set, the capsule has been successfully processed by the firmware.
+ If it set, the ScattlerGatherList is successfully to be set.
+ EFI_INVALID_PARAMETER CapsuleCount is less than 1,CapsuleGuid is not supported.
+ EFI_DEVICE_ERROR Failed to SetVariable or AllocatePool or ProcessFirmwareVolume.
+
+--*/
+{
+ UINTN CapsuleSize;
+ UINTN ArrayNumber;
+ VOID *BufferPtr;
+ EFI_STATUS Status;
+ EFI_HANDLE FvHandle;
+ UEFI_CAPSULE_HEADER *CapsuleHeader;
+
+ if (CapsuleCount < 1) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ BufferPtr = NULL;
+ CapsuleHeader = NULL;
+
+ //
+ //Compare GUIDs with EFI_CAPSULE_GUID, if capsule header contains CAPSULE_FLAGS_PERSIST_ACROSS_RESET
+ //and CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE flags,whatever the GUID is ,the service supports.
+ //
+ for (ArrayNumber = 0; ArrayNumber < CapsuleCount; ArrayNumber++) {
+ CapsuleHeader = CapsuleHeaderArray[ArrayNumber];
+ if ((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) && !(CapsuleHeader->Flags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET)) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if (!CompareGuid (&CapsuleHeader->CapsuleGuid, &mEfiCapsuleHeaderGuid)) {
+ if (!(CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE)) {
+ return EFI_UNSUPPORTED;
+ }
+ }
+ }
+
+ //
+ //Assume that capsules have the same flags on reseting or not.
+ //
+ CapsuleHeader = CapsuleHeaderArray[0];
+
+ if ((CapsuleHeader->Flags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET) != 0) {
+ //
+ //Check if the platform supports update capsule across a system reset
+ //
+ if (!FeaturePcdGet(PcdSupportUpdateCapsuleRest)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ if (ScatterGatherList == 0) {
+ return EFI_INVALID_PARAMETER;
+ } else {
+ Status = EfiSetVariable (
+ EFI_CAPSULE_VARIABLE_NAME,
+ &gEfiCapsuleVendorGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS,
+ sizeof (UINTN),
+ (VOID *) &ScatterGatherList
+ );
+ if (Status != EFI_SUCCESS) {
+ return EFI_DEVICE_ERROR;
+ }
+ }
+ return EFI_SUCCESS;
+ }
+
+ //
+ //The rest occurs in the condition of non-reset mode
+ //
+ if (EfiAtRuntime ()) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ //Here should be in the boot-time
+ //
+ for (ArrayNumber = 0; ArrayNumber < CapsuleCount ; ArrayNumber++) {
+ CapsuleHeader = CapsuleHeaderArray[ArrayNumber];
+ CapsuleSize = CapsuleHeader->CapsuleImageSize - CapsuleHeader->HeaderSize;
+ Status = gBS->AllocatePool (EfiBootServicesData, CapsuleSize, &BufferPtr);
+ if (Status != EFI_SUCCESS) {
+ goto Done;
+ }
+ gBS->CopyMem (BufferPtr, (UINT8*)CapsuleHeader+ CapsuleHeader->HeaderSize, CapsuleSize);
+
+ //
+ //Call DXE service ProcessFirmwareVolume to process immediatelly
+ //
+ Status = gDS->ProcessFirmwareVolume (BufferPtr, CapsuleSize, &FvHandle);
+ if (Status != EFI_SUCCESS) {
+ gBS->FreePool (BufferPtr);
+ return EFI_DEVICE_ERROR;
+ }
+ gDS->Dispatch ();
+ gBS->FreePool (BufferPtr);
+ }
+ return EFI_SUCCESS;
+
+Done:
+ if (BufferPtr != NULL) {
+ gBS->FreePool (BufferPtr);
+ }
+ return EFI_DEVICE_ERROR;
+}
+
+
+
+EFI_STATUS
+EFIAPI
+QueryCapsuleCapabilities (
+ IN UEFI_CAPSULE_HEADER **CapsuleHeaderArray,
+ IN UINTN CapsuleCount,
+ OUT UINT64 *MaxiumCapsuleSize,
+ OUT EFI_RESET_TYPE *ResetType
+ )
+/*++
+
+Routine Description:
+
+ This code is to query about capsule capability.
+
+Arguments:
+
+ CapsuleHeaderArray A array of pointers to capsule headers passed in
+ CapsuleCount The number of capsule
+ MaxiumCapsuleSize Max capsule size is supported
+ ResetType Reset type the capsule indicates, if reset is not needed,return EfiResetCold.
+ If reset is needed, return EfiResetWarm.
+
+Returns:
+
+ EFI STATUS
+ EFI_SUCCESS Valid answer returned
+ EFI_INVALID_PARAMETER MaxiumCapsuleSize is NULL,ResetType is NULL.CapsuleCount is less than 1,CapsuleGuid is not supported.
+ EFI_UNSUPPORTED The capsule type is not supported.
+
+--*/
+{
+ UINTN ArrayNumber;
+ UEFI_CAPSULE_HEADER *CapsuleHeader;
+
+ if (CapsuleCount < 1) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((MaxiumCapsuleSize == NULL) ||(ResetType == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ CapsuleHeader = NULL;
+
+ //
+ //Compare GUIDs with EFI_CAPSULE_GUID, if capsule header contains CAPSULE_FLAGS_PERSIST_ACROSS_RESET
+ //and CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE flags,whatever the GUID is ,the service supports.
+ //
+ for (ArrayNumber = 0; ArrayNumber < CapsuleCount; ArrayNumber++) {
+ CapsuleHeader = CapsuleHeaderArray[ArrayNumber];
+ if ((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) && !(CapsuleHeader->Flags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET)) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if (!CompareGuid (&CapsuleHeader->CapsuleGuid, &mEfiCapsuleHeaderGuid)) {
+ if (!(CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE)) {
+ return EFI_UNSUPPORTED;
+ }
+ }
+ }
+
+ //
+ //Assume that capsules have the same flags on reseting or not.
+ //
+ CapsuleHeader = CapsuleHeaderArray[0];
+ if ((CapsuleHeader->Flags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET) != 0) {
+ //
+ //Check if the platform supports update capsule across a system reset
+ //
+ if (!FeaturePcdGet(PcdSupportUpdateCapsuleRest)) {
+ return EFI_UNSUPPORTED;
+ }
+ *ResetType = EfiResetWarm;
+ *MaxiumCapsuleSize = FixedPcdGet32(PcdMaxSizePopulateCapsule);
+ } else {
+ *ResetType = EfiResetCold;
+ *MaxiumCapsuleSize = FixedPcdGet32(PcdMaxSizeNonPopulateCapsule);
+ }
+ return EFI_SUCCESS;
+}
+