/** The constructor function. @retval EFI_SUCCESS The constructor successfully . **/ EFI_STATUS EFIAPI EdkiiSystemCapsuleLibConstructor ( VOID ) { mImageFmpInfoSize = PcdGetSize(PcdEdkiiSystemFirmwareImageDescriptor); mImageFmpInfo = AllocateCopyPool (mImageFmpInfoSize, PcdGetPtr(PcdEdkiiSystemFirmwareImageDescriptor)); ASSERT(mImageFmpInfo != NULL); CopyGuid(&mEdkiiSystemFirmwareFileGuid, PcdGetPtr(PcdEdkiiSystemFirmwareFileGuid)); return EFI_SUCCESS; }
/** Return if this FMP is a system FMP or a device FMP, based upon FmpImageInfo. @param[in] FmpImageInfo A pointer to EFI_FIRMWARE_IMAGE_DESCRIPTOR @return TRUE It is a system FMP. @return FALSE It is a device FMP. **/ BOOLEAN IsSystemFmp ( IN EFI_FIRMWARE_IMAGE_DESCRIPTOR *FmpImageInfo ) { GUID *Guid; UINTN Count; UINTN Index; Guid = PcdGetPtr (PcdSystemFmpCapsuleImageTypeIdGuid); Count = PcdGetSize (PcdSystemFmpCapsuleImageTypeIdGuid) / sizeof(GUID); for (Index = 0; Index < Count; Index++, Guid++) { if (CompareGuid (&FmpImageInfo->ImageTypeId, Guid)) { return TRUE; } } return FALSE; }
/** Return if this FMP is a system FMP or a device FMP, based upon FmpImageInfo. @param[in] FmpImageHeader A pointer to EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER @return TRUE It is a system FMP. @return FALSE It is a device FMP. **/ BOOLEAN IsSystemFmpImage ( IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *FmpImageHeader ) { GUID *Guid; UINTN Count; UINTN Index; Guid = PcdGetPtr(PcdSystemFmpCapsuleImageTypeIdGuid); Count = PcdGetSize(PcdSystemFmpCapsuleImageTypeIdGuid) / sizeof(GUID); for (Index = 0; Index < Count; Index++, Guid++) { if (CompareGuid(&FmpImageHeader->UpdateImageTypeId, Guid)) { return TRUE; } } return FALSE; }
/** Installs the Device Recovery Module PPI, Initialize BlockIo Ppi installation notification @param FileHandle The file handle of the image. @param PeiServices General purpose services available to every PEIM. @retval EFI_SUCCESS The function completed successfully. @retval EFI_OUT_OF_RESOURCES There is not enough system memory. **/ EFI_STATUS EFIAPI CdExpressPeimEntry ( IN EFI_PEI_FILE_HANDLE FileHandle, IN CONST EFI_PEI_SERVICES **PeiServices ) { EFI_STATUS Status; PEI_CD_EXPRESS_PRIVATE_DATA *PrivateData; if (!EFI_ERROR (PeiServicesRegisterForShadow (FileHandle))) { return EFI_SUCCESS; } PrivateData = AllocatePages (EFI_SIZE_TO_PAGES (sizeof (*PrivateData))); if (PrivateData == NULL) { return EFI_OUT_OF_RESOURCES; } mRecoveryFileNameSize = PcdGetSize(PcdRecoveryFileName) / sizeof(CHAR16); mRecoveryFileName = AllocatePool(mRecoveryFileNameSize); if (mRecoveryFileName == NULL) { return EFI_OUT_OF_RESOURCES; } Status = UnicodeStrToAsciiStrS(PcdGetPtr(PcdRecoveryFileName), mRecoveryFileName, mRecoveryFileNameSize); if (EFI_ERROR(Status)) { return Status; } // // Initialize Private Data (to zero, as is required by subsequent operations) // ZeroMem (PrivateData, sizeof (*PrivateData)); PrivateData->Signature = PEI_CD_EXPRESS_PRIVATE_DATA_SIGNATURE; PrivateData->BlockBuffer = AllocatePages (EFI_SIZE_TO_PAGES (PEI_CD_BLOCK_SIZE)); if (PrivateData->BlockBuffer == NULL) { return EFI_OUT_OF_RESOURCES; } PrivateData->CapsuleCount = 0; Status = UpdateBlocksAndVolumes (PrivateData, TRUE); Status = UpdateBlocksAndVolumes (PrivateData, FALSE); // // Installs Ppi // PrivateData->DeviceRecoveryPpi.GetNumberRecoveryCapsules = GetNumberRecoveryCapsules; PrivateData->DeviceRecoveryPpi.GetRecoveryCapsuleInfo = GetRecoveryCapsuleInfo; PrivateData->DeviceRecoveryPpi.LoadRecoveryCapsule = LoadRecoveryCapsule; PrivateData->PpiDescriptor.Flags = (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST); PrivateData->PpiDescriptor.Guid = &gEfiPeiDeviceRecoveryModulePpiGuid; PrivateData->PpiDescriptor.Ppi = &PrivateData->DeviceRecoveryPpi; Status = PeiServicesInstallPpi (&PrivateData->PpiDescriptor); if (EFI_ERROR (Status)) { return EFI_OUT_OF_RESOURCES; } // // PrivateData is allocated now, set it to the module variable // mPrivateData = PrivateData; // // Installs Block Io Ppi notification function // PrivateData->NotifyDescriptor.Flags = ( EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK ); PrivateData->NotifyDescriptor.Guid = &gEfiPeiVirtualBlockIoPpiGuid; PrivateData->NotifyDescriptor.Notify = BlockIoNotifyEntry; PrivateData->NotifyDescriptor2.Flags = ( EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST ); PrivateData->NotifyDescriptor2.Guid = &gEfiPeiVirtualBlockIo2PpiGuid; PrivateData->NotifyDescriptor2.Notify = BlockIoNotifyEntry; return PeiServicesNotifyPpi (&PrivateData->NotifyDescriptor); }
/** Extract the authenticated image from an FMP capsule image. Caution: This function may receive untrusted input. @param[in] Image The FMP capsule image, including EFI_FIRMWARE_IMAGE_AUTHENTICATION. @param[in] ImageSize The size of FMP capsule image in bytes. @param[out] LastAttemptStatus The last attempt status, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR. @param[out] AuthenticatedImage The authenticated capsule image, excluding EFI_FIRMWARE_IMAGE_AUTHENTICATION. @param[out] AuthenticatedImageSize The size of the authenticated capsule image in bytes. @retval TRUE The authenticated image is extracted. @retval FALSE The authenticated image is not extracted. **/ BOOLEAN EFIAPI ExtractAuthenticatedImage ( IN VOID *Image, IN UINTN ImageSize, OUT UINT32 *LastAttemptStatus, OUT VOID **AuthenticatedImage, OUT UINTN *AuthenticatedImageSize ) { EFI_FIRMWARE_IMAGE_AUTHENTICATION *ImageAuth; EFI_STATUS Status; GUID *CertType; VOID *PublicKeyData; UINTN PublicKeyDataLength; DEBUG((DEBUG_INFO, "ExtractAuthenticatedImage - Image: 0x%08x - 0x%08x\n", (UINTN)Image, (UINTN)ImageSize)); *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INVALID_FORMAT; if ((Image == NULL) || (ImageSize == 0)) { return FALSE; } ImageAuth = (EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image; if (ImageSize < sizeof(EFI_FIRMWARE_IMAGE_AUTHENTICATION)) { DEBUG((DEBUG_ERROR, "ExtractAuthenticatedImage - ImageSize too small\n")); return FALSE; } if (ImageAuth->AuthInfo.Hdr.dwLength <= OFFSET_OF(WIN_CERTIFICATE_UEFI_GUID, CertData)) { DEBUG((DEBUG_ERROR, "ExtractAuthenticatedImage - dwLength too small\n")); return FALSE; } if (ImageAuth->AuthInfo.Hdr.dwLength > MAX_UINTN - sizeof(UINT64)) { DEBUG((DEBUG_ERROR, "ExtractAuthenticatedImage - dwLength too big\n")); return FALSE; } if (ImageSize <= sizeof(ImageAuth->MonotonicCount) + ImageAuth->AuthInfo.Hdr.dwLength) { DEBUG((DEBUG_ERROR, "ExtractAuthenticatedImage - ImageSize too small\n")); return FALSE; } if (ImageAuth->AuthInfo.Hdr.wRevision != 0x0200) { DEBUG((DEBUG_ERROR, "ExtractAuthenticatedImage - wRevision: 0x%02x, expect - 0x%02x\n", (UINTN)ImageAuth->AuthInfo.Hdr.wRevision, (UINTN)0x0200)); return FALSE; } if (ImageAuth->AuthInfo.Hdr.wCertificateType != WIN_CERT_TYPE_EFI_GUID) { DEBUG((DEBUG_ERROR, "ExtractAuthenticatedImage - wCertificateType: 0x%02x, expect - 0x%02x\n", (UINTN)ImageAuth->AuthInfo.Hdr.wCertificateType, (UINTN)WIN_CERT_TYPE_EFI_GUID)); return FALSE; } CertType = &ImageAuth->AuthInfo.CertType; DEBUG((DEBUG_INFO, "ExtractAuthenticatedImage - CertType: %g\n", CertType)); if (CompareGuid(&gEfiCertPkcs7Guid, CertType)) { PublicKeyData = PcdGetPtr(PcdPkcs7CertBuffer); PublicKeyDataLength = PcdGetSize(PcdPkcs7CertBuffer); } else if (CompareGuid(&gEfiCertTypeRsa2048Sha256Guid, CertType)) { PublicKeyData = PcdGetPtr(PcdRsa2048Sha256PublicKeyBuffer); PublicKeyDataLength = PcdGetSize(PcdRsa2048Sha256PublicKeyBuffer); } else { return FALSE; } ASSERT (PublicKeyData != NULL); ASSERT (PublicKeyDataLength != 0); Status = AuthenticateFmpImage( ImageAuth, ImageSize, PublicKeyData, PublicKeyDataLength ); switch (Status) { case RETURN_SUCCESS: *LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS; break; case RETURN_SECURITY_VIOLATION: *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_AUTH_ERROR; break; case RETURN_INVALID_PARAMETER: *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INVALID_FORMAT; break; case RETURN_UNSUPPORTED: *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INVALID_FORMAT; break; case RETURN_OUT_OF_RESOURCES: *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INSUFFICIENT_RESOURCES; break; default: *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL; break; } if (EFI_ERROR(Status)) { return FALSE; } if (AuthenticatedImage != NULL) { *AuthenticatedImage = (UINT8 *)ImageAuth + ImageAuth->AuthInfo.Hdr.dwLength + sizeof(ImageAuth->MonotonicCount); } if (AuthenticatedImageSize != NULL) { *AuthenticatedImageSize = ImageSize - ImageAuth->AuthInfo.Hdr.dwLength - sizeof(ImageAuth->MonotonicCount); } return TRUE; }