--- /dev/null
+/** @file\r
+ Capsule Library instance to update capsule image to flash.\r
+\r
+ Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.<BR>\r
+\r
+ 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
+\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
+**/\r
+#include <PiDxe.h>\r
+#include <Guid/Capsule.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/DxeServicesTableLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/CapsuleLib.h>\r
+\r
+/**\r
+ Those capsules supported by the firmwares.\r
+\r
+ @param CapsuleHeader Points to a capsule header.\r
+\r
+ @retval EFI_SUCESS Input capsule is supported by firmware.\r
+ @retval EFI_UNSUPPORTED Input capsule is not supported by the firmware.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SupportCapsuleImage (\r
+ IN EFI_CAPSULE_HEADER *CapsuleHeader\r
+ )\r
+{\r
+ if (CompareGuid (&gEfiCapsuleGuid, &CapsuleHeader->CapsuleGuid)) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ return EFI_UNSUPPORTED;\r
+}\r
+\r
+/**\r
+ The firmware implements to process the capsule image.\r
+\r
+ @param CapsuleHeader Points to a capsule header.\r
+\r
+ @retval EFI_SUCESS Process Capsule Image successfully.\r
+ @retval EFI_UNSUPPORTED Capsule image is not supported by the firmware.\r
+ @retval EFI_VOLUME_CORRUPTED FV volume in the capsule is corrupted.\r
+ @retval EFI_OUT_OF_RESOURCES Not enough memory.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ProcessCapsuleImage (\r
+ IN EFI_CAPSULE_HEADER *CapsuleHeader\r
+ )\r
+{\r
+ UINT32 Length;\r
+ EFI_FIRMWARE_VOLUME_HEADER *FvImage;\r
+ EFI_FIRMWARE_VOLUME_HEADER *ProcessedFvImage;\r
+ EFI_STATUS Status;\r
+ EFI_HANDLE FvProtocolHandle;\r
+ UINT32 FvAlignment;\r
+\r
+ FvImage = NULL;\r
+ ProcessedFvImage = NULL;\r
+ Status = EFI_SUCCESS;\r
+\r
+ if (SupportCapsuleImage (CapsuleHeader) != EFI_SUCCESS) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ //\r
+ // Skip the capsule header, move to the Firware Volume\r
+ //\r
+ FvImage = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINT8 *) CapsuleHeader + CapsuleHeader->HeaderSize);\r
+ Length = CapsuleHeader->CapsuleImageSize - CapsuleHeader->HeaderSize;\r
+\r
+ while (Length != 0) {\r
+ //\r
+ // Point to the next firmware volume header, and then\r
+ // call the DXE service to process it.\r
+ //\r
+ if (FvImage->FvLength > (UINTN) Length) {\r
+ //\r
+ // Notes: need to stuff this status somewhere so that the\r
+ // error can be detected at OS runtime\r
+ //\r
+ Status = EFI_VOLUME_CORRUPTED;\r
+ break;\r
+ }\r
+\r
+ FvAlignment = 1 << ((FvImage->Attributes & EFI_FVB2_ALIGNMENT) >> 16);\r
+ //\r
+ // FvAlignment must be more than 8 bytes required by FvHeader structure.\r
+ //\r
+ if (FvAlignment < 8) {\r
+ FvAlignment = 8;\r
+ }\r
+ //\r
+ // Check FvImage Align is required.\r
+ //\r
+ if (((UINTN) FvImage % FvAlignment) == 0) {\r
+ ProcessedFvImage = FvImage;\r
+ } else {\r
+ //\r
+ // Allocate new aligned buffer to store FvImage.\r
+ //\r
+ ProcessedFvImage = (EFI_FIRMWARE_VOLUME_HEADER *) AllocateAlignedPages ((UINTN) EFI_SIZE_TO_PAGES (FvImage->FvLength), (UINTN) FvAlignment);\r
+ if (ProcessedFvImage == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ break;\r
+ }\r
+ CopyMem (ProcessedFvImage, FvImage, (UINTN) FvImage->FvLength);\r
+ }\r
+\r
+ Status = gDS->ProcessFirmwareVolume (\r
+ (VOID *) ProcessedFvImage,\r
+ (UINTN) ProcessedFvImage->FvLength,\r
+ &FvProtocolHandle\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ break;\r
+ }\r
+ //\r
+ // Call the dispatcher to dispatch any drivers from the produced firmware volume\r
+ //\r
+ gDS->Dispatch ();\r
+ //\r
+ // On to the next FV in the capsule\r
+ //\r
+ Length -= (UINT32) FvImage->FvLength;\r
+ FvImage = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINT8 *) FvImage + FvImage->FvLength);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+\r