summaryrefslogtreecommitdiffstats
path: root/MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.c
diff options
context:
space:
mode:
Diffstat (limited to 'MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.c')
-rw-r--r--MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.c442
1 files changed, 0 insertions, 442 deletions
diff --git a/MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.c b/MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.c
deleted file mode 100644
index ac96526bc2..0000000000
--- a/MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.c
+++ /dev/null
@@ -1,442 +0,0 @@
-/** @file
- Recovery module.
-
- Caution: This module requires additional review when modified.
- This module will have external input - Capsule-on-Disk Temp Relocation image.
- This external input must be validated carefully to avoid security issue like
- buffer overflow, integer overflow.
-
- RetrieveRelocatedCapsule() will receive untrusted input and do basic validation.
-
- Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
- SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-//
-// The package level header files this module uses
-//
-#include <Uefi.h>
-#include <PiPei.h>
-
-//
-// The protocols, PPI and GUID defintions for this module
-//
-#include <Ppi/MasterBootMode.h>
-#include <Ppi/FirmwareVolumeInfo.h>
-#include <Ppi/ReadOnlyVariable2.h>
-#include <Ppi/Capsule.h>
-#include <Ppi/CapsuleOnDisk.h>
-#include <Ppi/DeviceRecoveryModule.h>
-
-#include <Guid/FirmwareFileSystem2.h>
-//
-// The Library classes this module consumes
-//
-#include <Library/DebugLib.h>
-#include <Library/PeimEntryPoint.h>
-#include <Library/PeiServicesLib.h>
-#include <Library/HobLib.h>
-#include <Library/BaseMemoryLib.h>
-#include <Library/MemoryAllocationLib.h>
-#include <Library/PcdLib.h>
-#include <Library/CapsuleLib.h>
-#include <Library/ReportStatusCodeLib.h>
-
-/**
- Loads a DXE capsule from some media into memory and updates the HOB table
- with the DXE firmware volume information.
-
- @param[in] PeiServices General-purpose services that are available to every PEIM.
- @param[in] This Indicates the EFI_PEI_RECOVERY_MODULE_PPI instance.
-
- @retval EFI_SUCCESS The capsule was loaded correctly.
- @retval EFI_DEVICE_ERROR A device error occurred.
- @retval EFI_NOT_FOUND A recovery DXE capsule cannot be found.
-
-**/
-EFI_STATUS
-EFIAPI
-LoadCapsuleOnDisk (
- IN EFI_PEI_SERVICES **PeiServices,
- IN EFI_PEI_CAPSULE_ON_DISK_PPI *This
- );
-
-EFI_PEI_CAPSULE_ON_DISK_PPI mCapsuleOnDiskPpi = {
- LoadCapsuleOnDisk
-};
-
-EFI_PEI_PPI_DESCRIPTOR mCapsuleOnDiskPpiList = {
- (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
- &gEdkiiPeiCapsuleOnDiskPpiGuid,
- &mCapsuleOnDiskPpi
-};
-
-/**
- Determine if capsule comes from memory by checking Capsule PPI.
-
- @param[in] PeiServices General purpose services available to every PEIM.
-
- @retval TRUE Capsule comes from memory.
- @retval FALSE No capsule comes from memory.
-
-**/
-static
-BOOLEAN
-CheckCapsuleFromRam (
- IN CONST EFI_PEI_SERVICES **PeiServices
- )
-{
- EFI_STATUS Status;
- PEI_CAPSULE_PPI *Capsule;
-
- Status = PeiServicesLocatePpi (
- &gEfiPeiCapsulePpiGuid,
- 0,
- NULL,
- (VOID **) &Capsule
- );
- if (!EFI_ERROR(Status)) {
- Status = Capsule->CheckCapsuleUpdate ((EFI_PEI_SERVICES **)PeiServices);
- if (!EFI_ERROR(Status)) {
- return TRUE;
- }
- }
-
- return FALSE;
-}
-
-/**
- Determine if it is a Capsule On Disk mode.
-
- @retval TRUE Capsule On Disk mode.
- @retval FALSE Not capsule On Disk mode.
-
-**/
-BOOLEAN
-IsCapsuleOnDiskMode (
- VOID
- )
-{
- EFI_STATUS Status;
- UINTN Size;
- EFI_PEI_READ_ONLY_VARIABLE2_PPI *PPIVariableServices;
- BOOLEAN CodRelocInfo;
-
- Status = PeiServicesLocatePpi (
- &gEfiPeiReadOnlyVariable2PpiGuid,
- 0,
- NULL,
- (VOID **) &PPIVariableServices
- );
- ASSERT_EFI_ERROR (Status);
-
- Size = sizeof (BOOLEAN);
- Status = PPIVariableServices->GetVariable (
- PPIVariableServices,
- COD_RELOCATION_INFO_VAR_NAME,
- &gEfiCapsuleVendorGuid,
- NULL,
- &Size,
- &CodRelocInfo
- );
-
- if (EFI_ERROR (Status) || Size != sizeof(BOOLEAN) || !CodRelocInfo) {
- DEBUG (( DEBUG_ERROR, "Error Get CodRelocationInfo variable %r!\n", Status));
- return FALSE;
- }
-
- return TRUE;
-}
-
-/**
- Gets capsule images from relocated capsule buffer.
- Create Capsule hob for each Capsule.
-
- Caution: This function may receive untrusted input.
- Capsule-on-Disk Temp Relocation image is external input, so this function
- will validate Capsule-on-Disk Temp Relocation image to make sure the content
- is read within the buffer.
-
- @param[in] RelocCapsuleBuf Buffer pointer to the relocated capsule.
- @param[in] RelocCapsuleTotalSize Total size of the relocated capsule.
-
- @retval EFI_SUCCESS Succeed to get capsules and create hob.
- @retval Others Fail to get capsules and create hob.
-
-**/
-EFI_STATUS
-EFIAPI
-RetrieveRelocatedCapsule (
- IN UINT8 *RelocCapsuleBuf,
- IN UINTN RelocCapsuleTotalSize
- )
-{
- EFI_STATUS Status;
- UINTN Index;
- UINT8 *CapsuleDataBufEnd;
- UINT8 *CapsulePtr;
- UINT32 CapsuleSize;
- UINT64 TotalImageSize;
- UINTN CapsuleNum;
-
- CapsuleNum = 0;
-
- //
- // Temp file contains at least 2 capsule (including 1 capsule name capsule) & 1 UINT64
- //
- if (RelocCapsuleTotalSize < sizeof(UINT64) + sizeof(EFI_CAPSULE_HEADER) * 2) {
- return EFI_INVALID_PARAMETER;
- }
-
- CopyMem(&TotalImageSize, RelocCapsuleBuf, sizeof(UINT64));
-
- DEBUG ((DEBUG_INFO, "ProcessRelocatedCapsule CapsuleBuf %x TotalCapSize %lx\n",
- RelocCapsuleBuf, TotalImageSize));
-
- RelocCapsuleBuf += sizeof(UINT64);
-
- //
- // TempCaspule file length check
- //
- if (MAX_ADDRESS - TotalImageSize <= sizeof(UINT64) ||
- (UINT64)RelocCapsuleTotalSize != TotalImageSize + sizeof(UINT64) ||
- (UINTN)(MAX_ADDRESS - (PHYSICAL_ADDRESS)(UINTN)RelocCapsuleBuf) <= TotalImageSize) {
- return EFI_INVALID_PARAMETER;
- }
-
- CapsuleDataBufEnd = RelocCapsuleBuf + TotalImageSize;
-
- //
- // TempCapsule file integrity check over Capsule Header to ensure no data corruption in NV Var & Relocation storage
- //
- CapsulePtr = RelocCapsuleBuf;
-
- while (CapsulePtr < CapsuleDataBufEnd) {
- if ((CapsuleDataBufEnd - CapsulePtr) < sizeof(EFI_CAPSULE_HEADER) ||
- ((EFI_CAPSULE_HEADER *)CapsulePtr)->CapsuleImageSize < sizeof(EFI_CAPSULE_HEADER) ||
- (UINTN)(MAX_ADDRESS - (PHYSICAL_ADDRESS)(UINTN)CapsulePtr) < ((EFI_CAPSULE_HEADER *)CapsulePtr)->CapsuleImageSize
- ) {
- break;
- }
- CapsulePtr += ((EFI_CAPSULE_HEADER *)CapsulePtr)->CapsuleImageSize;
- CapsuleNum ++;
- }
-
- if (CapsulePtr != CapsuleDataBufEnd) {
- Status = EFI_INVALID_PARAMETER;
- goto EXIT;
- }
-
- //
- // Capsule count must be less than PcdCapsuleMax, avoid building too many CvHobs to occupy all the free space in HobList.
- //
- if (CapsuleNum > PcdGet16 (PcdCapsuleMax)) {
- Status = EFI_INVALID_PARAMETER;
- goto EXIT;
- }
-
- //
- // Re-iterate the capsule buffer to create Capsule hob & Capsule Name Str Hob for each Capsule saved in relocated capsule file
- //
- CapsulePtr = RelocCapsuleBuf;
- Index = 0;
- while (CapsulePtr < CapsuleDataBufEnd) {
- CapsuleSize = ((EFI_CAPSULE_HEADER *)CapsulePtr)->CapsuleImageSize;
- BuildCvHob ((EFI_PHYSICAL_ADDRESS)(UINTN)CapsulePtr, CapsuleSize);
-
- DEBUG((DEBUG_INFO, "Capsule saved in address %x size %x\n", CapsulePtr, CapsuleSize));
-
- CapsulePtr += CapsuleSize;
- Index++;
- }
-
-EXIT:
-
- return Status;
-}
-
-/**
- Recovery module entrypoint
-
- @param[in] FileHandle Handle of the file being invoked.
- @param[in] PeiServices Describes the list of possible PEI Services.
-
- @return EFI_SUCCESS Recovery module is initialized.
-**/
-EFI_STATUS
-EFIAPI
-InitializeCapsuleOnDiskLoad (
- IN EFI_PEI_FILE_HANDLE FileHandle,
- IN CONST EFI_PEI_SERVICES **PeiServices
- )
-{
- EFI_STATUS Status;
- UINTN BootMode;
- UINTN FileNameSize;
-
- BootMode = GetBootModeHob();
- ASSERT(BootMode == BOOT_ON_FLASH_UPDATE);
-
- //
- // If there are capsules provisioned in memory, quit.
- // Only one capsule resource is accept, CapsuleOnRam's priority is higher than CapsuleOnDisk.
- //
- if (CheckCapsuleFromRam(PeiServices)) {
- DEBUG((DEBUG_ERROR, "Capsule On Memory Detected! Quit.\n"));
- return EFI_ABORTED;
- }
-
- DEBUG_CODE (
- VOID *CapsuleOnDiskModePpi;
-
- if (!IsCapsuleOnDiskMode()){
- return EFI_NOT_FOUND;
- }
-
- //
- // Check Capsule On Disk Relocation flag. If exists, load capsule & create Capsule Hob
- //
- Status = PeiServicesLocatePpi (
- &gEdkiiPeiBootInCapsuleOnDiskModePpiGuid,
- 0,
- NULL,
- (VOID **)&CapsuleOnDiskModePpi
- );
- if (EFI_ERROR(Status)) {
- DEBUG((DEBUG_ERROR, "Locate CapsuleOnDiskModePpi error %x\n", Status));
- return Status;
- }
- );
-
- Status = PeiServicesInstallPpi (&mCapsuleOnDiskPpiList);
- ASSERT_EFI_ERROR (Status);
-
- FileNameSize = PcdGetSize (PcdCoDRelocationFileName);
- Status = PcdSetPtrS (PcdRecoveryFileName, &FileNameSize, (VOID *) PcdGetPtr(PcdCoDRelocationFileName));
- ASSERT_EFI_ERROR (Status);
-
- return Status;
-}
-
-/**
- Loads a DXE capsule from some media into memory and updates the HOB table
- with the DXE firmware volume information.
-
- @param[in] PeiServices General-purpose services that are available to every PEIM.
- @param[in] This Indicates the EFI_PEI_RECOVERY_MODULE_PPI instance.
-
- @retval EFI_SUCCESS The capsule was loaded correctly.
- @retval EFI_DEVICE_ERROR A device error occurred.
- @retval EFI_NOT_FOUND A recovery DXE capsule cannot be found.
-
-**/
-EFI_STATUS
-EFIAPI
-LoadCapsuleOnDisk (
- IN EFI_PEI_SERVICES **PeiServices,
- IN EFI_PEI_CAPSULE_ON_DISK_PPI *This
- )
-{
- EFI_STATUS Status;
- EFI_PEI_DEVICE_RECOVERY_MODULE_PPI *DeviceRecoveryPpi;
- UINTN NumberRecoveryCapsules;
- UINTN Instance;
- UINTN CapsuleInstance;
- UINTN CapsuleSize;
- EFI_GUID CapsuleType;
- VOID *CapsuleBuffer;
-
- DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Load Capsule On Disk Entry\n"));
-
- for (Instance = 0; ; Instance++) {
- Status = PeiServicesLocatePpi (
- &gEfiPeiDeviceRecoveryModulePpiGuid,
- Instance,
- NULL,
- (VOID **)&DeviceRecoveryPpi
- );
- DEBUG ((DEBUG_INFO, "LoadCapsuleOnDisk - LocateRecoveryPpi (%d) - %r\n", Instance, Status));
- if (EFI_ERROR (Status)) {
- if (Instance == 0) {
- REPORT_STATUS_CODE (
- EFI_ERROR_CODE | EFI_ERROR_MAJOR,
- (EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_EC_RECOVERY_PPI_NOT_FOUND)
- );
- }
- break;
- }
- NumberRecoveryCapsules = 0;
- Status = DeviceRecoveryPpi->GetNumberRecoveryCapsules (
- (EFI_PEI_SERVICES **)PeiServices,
- DeviceRecoveryPpi,
- &NumberRecoveryCapsules
- );
- DEBUG ((DEBUG_INFO, "LoadCapsuleOnDisk - GetNumberRecoveryCapsules (%d) - %r\n", NumberRecoveryCapsules, Status));
- if (EFI_ERROR (Status)) {
- continue;
- }
-
- for (CapsuleInstance = 1; CapsuleInstance <= NumberRecoveryCapsules; CapsuleInstance++) {
- CapsuleSize = 0;
- Status = DeviceRecoveryPpi->GetRecoveryCapsuleInfo (
- (EFI_PEI_SERVICES **)PeiServices,
- DeviceRecoveryPpi,
- CapsuleInstance,
- &CapsuleSize,
- &CapsuleType
- );
- DEBUG ((DEBUG_INFO, "LoadCapsuleOnDisk - GetRecoveryCapsuleInfo (%d - %x) - %r\n", CapsuleInstance, CapsuleSize, Status));
- if (EFI_ERROR (Status)) {
- break;
- }
-
- //
- // Allocate the memory so that it gets preserved into DXE.
- // Capsule is special because it may need to populate to system table
- //
- CapsuleBuffer = AllocateRuntimePages (EFI_SIZE_TO_PAGES (CapsuleSize));
-
- if (CapsuleBuffer == NULL) {
- DEBUG ((DEBUG_ERROR, "LoadCapsuleOnDisk - AllocateRuntimePages fail\n"));
- continue;
- }
-
- Status = DeviceRecoveryPpi->LoadRecoveryCapsule (
- (EFI_PEI_SERVICES **)PeiServices,
- DeviceRecoveryPpi,
- CapsuleInstance,
- CapsuleBuffer
- );
- DEBUG ((DEBUG_INFO, "LoadCapsuleOnDisk - LoadRecoveryCapsule (%d) - %r\n", CapsuleInstance, Status));
- if (EFI_ERROR (Status)) {
- FreePages (CapsuleBuffer, EFI_SIZE_TO_PAGES(CapsuleSize));
- break;
- }
-
- //
- // Capsule Update Mode, Split relocated Capsule buffer into different capsule vehical hobs.
- //
- Status = RetrieveRelocatedCapsule(CapsuleBuffer, CapsuleSize);
-
- break;
- }
-
- if (EFI_ERROR (Status)) {
- REPORT_STATUS_CODE (
- EFI_ERROR_CODE | EFI_ERROR_MAJOR,
- (EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_EC_NO_RECOVERY_CAPSULE)
- );
- }
-
- return Status;
- }
-
- //
- // Any attack against GPT, Relocation Info Variable or temp relocation file will result in no Capsule HOB and return EFI_NOT_FOUND.
- // After flow to DXE phase. since no capsule hob is detected. Platform will clear Info flag and force restart.
- // No volunerability will be exposed
- //
-
- return EFI_NOT_FOUND;
-}