diff --git a/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf b/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf new file mode 100644 index 0000000000..23ad32720e --- /dev/null +++ b/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf @@ -0,0 +1,76 @@ +#/** @file +# Component description file for Capsule module. +# +# CapsuleRuntime module provides capsule runtime services +# Copyright (c) 2006 - 2007, 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. +# +# +#**/ + +################################################################################ +# +# Defines Section - statements that will be processed to create a Makefile. +# +################################################################################ +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = CapsuleRuntimeDxe + FILE_GUID = 42857F0A-13F2-4B21-8A23-53D3F714B840 + MODULE_TYPE = DXE_RUNTIME_DRIVER + VERSION_STRING = 1.0 + EDK_RELEASE_VERSION = 0x00020000 + EFI_SPECIFICATION_VERSION = 0x00020000 + + ENTRY_POINT = CapsuleServiceInitialize + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +################################################################################ +# +# Sources Section - list of files that are required for the build to succeed. +# +################################################################################ + +[Sources.common] + CapsuleService.h + CapsuleService.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + UefiBootServicesTableLib + MemoryAllocationLib + BaseMemoryLib + PcdLib + DebugLib + UefiRuntimeLib + DxeServicesTableLib + UefiDriverEntryPoint + +[Guids] + gEfiCapsuleVendorGuid # SOMETIMES_CONSUMED + +[Protocols] + gEfiCapsuleArchProtocolGuid # PROTOCOL ALWAYS_CONSUMED + +[PcdsFeatureFlag.common] + PcdSupportUpdateCapsuleRest|gEfiMdeModulePkgTokenSpaceGuid + +[PcdsFixedAtBuild.common] + PcdMaxSizeNonPopulateCapsule|gEfiMdeModulePkgTokenSpaceGuid + PcdMaxSizePopulateCapsule|gEfiMdeModulePkgTokenSpaceGuid + +[Depex] + gEfiVariableArchProtocolGuid diff --git a/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.msa b/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.msa new file mode 100644 index 0000000000..346cc7f32f --- /dev/null +++ b/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.msa @@ -0,0 +1,95 @@ + + + + CapsuleRuntime + DXE_RUNTIME_DRIVER + 42857F0A-13F2-4B21-8A23-53D3F714B840 + 1.0 + Component description file for Capsule module. + CapsuleRuntime module provides capsule runtime services + Copyright (c) 2006 - 2007, 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. + FRAMEWORK_BUILD_PACKAGING_SPECIFICATION 0x00000052 + + + IA32 X64 IPF EBC + false + CapsuleRuntime + + + + UefiDriverEntryPoint + + + DxeServicesTableLib + + + UefiRuntimeLib + + + DebugLib + + + PcdLib + + + BaseMemoryLib + + + MemoryAllocationLib + + + UefiBootServicesTableLib + + + + Capsule.c + CapsuleService.c + CapsuleService.h + Capsule.dxs + + + + + + + + + gEfiCapsuleArchProtocolGuid + + + + + gEfiCapsuleVendorGuid + + + + EFI_SPECIFICATION_VERSION 0x00020000 + EDK_RELEASE_VERSION 0x00020000 + + CapsuleServiceInitialize + + + + + PcdSupportUpdateCapsuleRest + gEfiEdkModulePkgTokenSpaceGuid + Indicate whether platform can support update capsule across a system reset + + + PcdMaxSizePopulateCapsule + gEfiEdkModulePkgTokenSpaceGuid + Indicate the max size the platform can support in case of populated capsules + + + PcdMaxSizeNonPopulateCapsule + gEfiEdkModulePkgTokenSpaceGuid + Indicate the max size the platform can support in case of non-populated capsules + + + diff --git a/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleService.c b/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleService.c new file mode 100644 index 0000000000..5a923cda34 --- /dev/null +++ b/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleService.c @@ -0,0 +1,264 @@ +/*++ + +Copyright (c) 2006 - 2007, 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" + +EFI_STATUS +EFIAPI +UpdateCapsule ( + IN EFI_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; + EFI_CAPSULE_HEADER *CapsuleHeader; + + if (CapsuleCount < 1) { + return EFI_INVALID_PARAMETER; + } + + BufferPtr = NULL; + CapsuleHeader = NULL; + + for (ArrayNumber = 0; ArrayNumber < CapsuleCount; ArrayNumber++) { + CapsuleHeader = CapsuleHeaderArray[ArrayNumber]; + if ((CapsuleHeader->Flags & (CAPSULE_FLAGS_PERSIST_ACROSS_RESET | CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE)) == CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) { + return EFI_INVALID_PARAMETER; + } + if ((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) == 0) { + 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; + + BufferPtr = AllocatePool (CapsuleSize); + if (BufferPtr == NULL) { + return EFI_DEVICE_ERROR; + } + + CopyMem (BufferPtr, (UINT8*)CapsuleHeader+ CapsuleHeader->HeaderSize, CapsuleSize); + + // + //Call DXE service ProcessFirmwareVolume to process immediatelly + // + Status = gDS->ProcessFirmwareVolume (BufferPtr, CapsuleSize, &FvHandle); + if (Status != EFI_SUCCESS) { + FreePool (BufferPtr); + return EFI_DEVICE_ERROR; + } + gDS->Dispatch (); + FreePool (BufferPtr); + } + + return EFI_SUCCESS; +} + + + +EFI_STATUS +EFIAPI +QueryCapsuleCapabilities ( + IN EFI_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; + EFI_CAPSULE_HEADER *CapsuleHeader; + + if (CapsuleCount < 1) { + return EFI_INVALID_PARAMETER; + } + + if ((MaxiumCapsuleSize == NULL) ||(ResetType == NULL)) { + return EFI_INVALID_PARAMETER; + } + + CapsuleHeader = NULL; + + for (ArrayNumber = 0; ArrayNumber < CapsuleCount; ArrayNumber++) { + CapsuleHeader = CapsuleHeaderArray[ArrayNumber]; + if ((CapsuleHeader->Flags & (CAPSULE_FLAGS_PERSIST_ACROSS_RESET | CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE)) == CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) { + return EFI_INVALID_PARAMETER; + } + if ((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) == 0) { + 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; +} + + +EFI_STATUS +EFIAPI +CapsuleServiceInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/*++ + +Routine Description: + + This code is capsule runtime service initialization. + +Arguments: + + ImageHandle The image handle + SystemTable The system table. + +Returns: + + EFI STATUS + +--*/ +{ + EFI_STATUS Status; + EFI_HANDLE NewHandle; + + SystemTable->RuntimeServices->UpdateCapsule = UpdateCapsule; + SystemTable->RuntimeServices->QueryCapsuleCapabilities = QueryCapsuleCapabilities; + + // + // Now install the Capsule Architectural Protocol on a new handle + // + NewHandle = NULL; + + Status = gBS->InstallMultipleProtocolInterfaces ( + &NewHandle, + &gEfiCapsuleArchProtocolGuid, + NULL, + NULL + ); + ASSERT_EFI_ERROR (Status); + + return EFI_SUCCESS; +} diff --git a/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleService.h b/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleService.h new file mode 100644 index 0000000000..8e02b63279 --- /dev/null +++ b/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleService.h @@ -0,0 +1,68 @@ +/*++ + +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.h + +Abstract: + + Capsule Runtime Service + +--*/ + +#ifndef _CAPSULE_RUNTIME_H_ +#define _CAPSULE_RUNTIME_H_ + +// +// The package level header files this module uses +// +#include +// +// The protocols, PPI and GUID defintions for this module +// +#include +#include +// +// The Library classes this module consumes +// +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +extern EFI_GUID gEfiCapsuleGuid; + +EFI_STATUS +EFIAPI +UpdateCapsule( + IN EFI_CAPSULE_HEADER **CapsuleHeaderArray, + IN UINTN CapsuleCount, + IN EFI_PHYSICAL_ADDRESS ScatterGatherList OPTIONAL + ); + +EFI_STATUS +EFIAPI +QueryCapsuleCapabilities( + IN EFI_CAPSULE_HEADER **CapsuleHeaderArray, + IN UINTN CapsuleCount, + OUT UINT64 *MaxiumCapsuleSize, + OUT EFI_RESET_TYPE *ResetType + ); + +#endif +