public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Kinney, Michael D" <michael.d.kinney@intel.com>
To: "Yao, Jiewen" <jiewen.yao@intel.com>,
	"edk2-devel@lists.01.org" <edk2-devel@lists.01.org>,
	"Kinney, Michael D" <michael.d.kinney@intel.com>
Cc: "Tian, Feng" <feng.tian@intel.com>,
	"Zeng, Star" <star.zeng@intel.com>,
	"Gao, Liming" <liming.gao@intel.com>,
	"Zhang, Chao B" <chao.b.zhang@intel.com>
Subject: Re: [PATCH V4 08/15] MdeModulePkg/CapsuleApp: Add CapsuleApp application.
Date: Thu, 27 Oct 2016 00:13:14 +0000	[thread overview]
Message-ID: <E92EE9817A31E24EB0585FDF735412F56483B94F@ORSMSX113.amr.corp.intel.com> (raw)
In-Reply-To: <1477189240-11336-9-git-send-email-jiewen.yao@intel.com>

Jiewen,

I have looked Microsoft UX capsule in the Microsoft
Windows UEFI Firmware Update Platform Specification, and 
that specification only defines support for an ImageType value
of 0, which is bitmap format based on ACPI 5.0 BGRT.  There
are no defined ImageType values for BMP. 

I recommend you update the capsule app for the unit test
that tests the bitmap capability to require the file to
be the same format as required by the Windows UEFI Firmware 
Update Platform Specification, and the variables and comments
in this patch should not reference the BMP file format at all.

A developer that wants to test this capability must convert
a graphics image to the right format before using it with
this utility.

Thanks,

Mike

> -----Original Message-----
> From: Yao, Jiewen
> Sent: Saturday, October 22, 2016 7:21 PM
> To: edk2-devel@lists.01.org
> Cc: Tian, Feng <feng.tian@intel.com>; Zeng, Star <star.zeng@intel.com>; Kinney, Michael
> D <michael.d.kinney@intel.com>; Gao, Liming <liming.gao@intel.com>; Zhang, Chao B
> <chao.b.zhang@intel.com>
> Subject: [PATCH V4 08/15] MdeModulePkg/CapsuleApp: Add CapsuleApp application.
> 
> This CapsuleApp can help perform capsule update in UEFI shell environment.
> It can also dump capsule information, capsule status variable, ESRT and FMP.
> 
> Cc: Feng Tian <feng.tian@intel.com>
> Cc: Star Zeng <star.zeng@intel.com>
> Cc: Michael D Kinney <michael.d.kinney@intel.com>
> Cc: Liming Gao <liming.gao@intel.com>
> Cc: Chao Zhang <chao.b.zhang@intel.com>
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
> Reviewed-by: Liming Gao <liming.gao@intel.com>
> ---
>  MdeModulePkg/Application/CapsuleApp/AppSupport.c        | 445 ++++++++++
>  MdeModulePkg/Application/CapsuleApp/CapsuleApp.c        | 853 ++++++++++++++++++++
>  MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf      |  71 ++
>  MdeModulePkg/Application/CapsuleApp/CapsuleApp.uni      |  22 +
>  MdeModulePkg/Application/CapsuleApp/CapsuleAppExtra.uni |  19 +
>  MdeModulePkg/Application/CapsuleApp/CapsuleDump.c       | 740 +++++++++++++++++
>  6 files changed, 2150 insertions(+)
> 
> diff --git a/MdeModulePkg/Application/CapsuleApp/AppSupport.c
> b/MdeModulePkg/Application/CapsuleApp/AppSupport.c
> new file mode 100644
> index 0000000..90ca1fd
> --- /dev/null
> +++ b/MdeModulePkg/Application/CapsuleApp/AppSupport.c
> @@ -0,0 +1,445 @@
> +/** @file
> +  A shell application that triggers capsule update process.
> +
> +  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
> +  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.
> +
> +**/
> +
> +#include <Uefi.h>
> +#include <Library/BaseLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/UefiRuntimeServicesTableLib.h>
> +#include <Library/UefiLib.h>
> +#include <Library/PrintLib.h>
> +#include <Protocol/LoadedImage.h>
> +#include <Protocol/SimpleFileSystem.h>
> +#include <Protocol/ShellParameters.h>
> +#include <Guid/FileInfo.h>
> +#include <Guid/Gpt.h>
> +
> +#define MAX_ARG_NUM     11
> +
> +UINTN  Argc;
> +CHAR16 **Argv;
> +
> +/**
> +
> +  This function parse application ARG.
> +
> +  @return Status
> +**/
> +EFI_STATUS
> +GetArg (
> +  VOID
> +  )
> +{
> +  EFI_STATUS                    Status;
> +  EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters;
> +
> +  Status = gBS->HandleProtocol (
> +                  gImageHandle,
> +                  &gEfiShellParametersProtocolGuid,
> +                  (VOID**)&ShellParameters
> +                  );
> +  if (EFI_ERROR(Status)) {
> +    return Status;
> +  }
> +
> +  Argc = ShellParameters->Argc;
> +  Argv = ShellParameters->Argv;
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Return File System Volume containing this shell application.
> +
> +  @return File System Volume containing this shell application.
> +**/
> +EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *
> +GetMyVol (
> +  VOID
> +  )
> +{
> +  EFI_STATUS                        Status;
> +  EFI_LOADED_IMAGE_PROTOCOL         *LoadedImage;
> +  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Vol;
> +
> +  Status = gBS->HandleProtocol (
> +                  gImageHandle,
> +                  &gEfiLoadedImageProtocolGuid,
> +                  (VOID **)&LoadedImage
> +                  );
> +  ASSERT_EFI_ERROR (Status);
> +
> +  Status = gBS->HandleProtocol (
> +                  LoadedImage->DeviceHandle,
> +                  &gEfiSimpleFileSystemProtocolGuid,
> +                  (VOID **)&Vol
> +                  );
> +  if (!EFI_ERROR (Status)) {
> +    return Vol;
> +  }
> +
> +  return NULL;
> +}
> +
> +/**
> +  Read a file from this volume.
> +
> +  @param Vol             File System Volume
> +  @param FileName        The file to be read.
> +  @param BufferSize      The file buffer size
> +  @param Buffer          The file buffer
> +
> +  @retval EFI_SUCCESS    Read file successfully
> +  @retval EFI_NOT_FOUND  File not found
> +**/
> +EFI_STATUS
> +ReadFileFromVol (
> +  IN  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Vol,
> +  IN  CHAR16                            *FileName,
> +  OUT UINTN                             *BufferSize,
> +  OUT VOID                              **Buffer
> +  )
> +{
> +  EFI_STATUS                        Status;
> +  EFI_FILE_HANDLE                   RootDir;
> +  EFI_FILE_HANDLE                   Handle;
> +  UINTN                             FileInfoSize;
> +  EFI_FILE_INFO                     *FileInfo;
> +  UINTN                             TempBufferSize;
> +  VOID                              *TempBuffer;
> +
> +  //
> +  // Open the root directory
> +  //
> +  Status = Vol->OpenVolume (Vol, &RootDir);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  //
> +  // Open the file
> +  //
> +  Status = RootDir->Open (
> +                      RootDir,
> +                      &Handle,
> +                      FileName,
> +                      EFI_FILE_MODE_READ,
> +                      0
> +                      );
> +  if (EFI_ERROR (Status)) {
> +    RootDir->Close (RootDir);
> +    return Status;
> +  }
> +
> +  RootDir->Close (RootDir);
> +
> +  //
> +  // Get the file information
> +  //
> +  FileInfoSize = sizeof(EFI_FILE_INFO) + 1024;
> +
> +  FileInfo = AllocateZeroPool (FileInfoSize);
> +  if (FileInfo == NULL) {
> +    Handle->Close (Handle);
> +    return Status;
> +  }
> +
> +  Status = Handle->GetInfo (
> +                     Handle,
> +                     &gEfiFileInfoGuid,
> +                     &FileInfoSize,
> +                     FileInfo
> +                     );
> +  if (EFI_ERROR (Status)) {
> +    Handle->Close (Handle);
> +    gBS->FreePool (FileInfo);
> +    return Status;
> +  }
> +
> +  //
> +  // Allocate buffer for the file data. The last CHAR16 is for L'\0'
> +  //
> +  TempBufferSize = (UINTN) FileInfo->FileSize + sizeof(CHAR16);
> +  TempBuffer = AllocateZeroPool (TempBufferSize);
> +  if (TempBuffer == NULL) {
> +    Handle->Close (Handle);
> +    gBS->FreePool (FileInfo);
> +    return Status;
> +  }
> +
> +  gBS->FreePool (FileInfo);
> +
> +  //
> +  // Read the file data to the buffer
> +  //
> +  Status = Handle->Read (
> +                     Handle,
> +                     &TempBufferSize,
> +                     TempBuffer
> +                     );
> +  if (EFI_ERROR (Status)) {
> +    Handle->Close (Handle);
> +    gBS->FreePool (TempBuffer);
> +    return Status;
> +  }
> +
> +  Handle->Close (Handle);
> +
> +  *BufferSize = TempBufferSize;
> +  *Buffer     = TempBuffer;
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Read a file.
> +  If ScanFs is FLASE, it will use this Vol as default Fs.
> +  If ScanFs is TRUE, it will scan all FS and check the file.
> +    If there is only one file match the name, it will be read.
> +    If there is more than one file match the name, it will return Error.
> +
> +  @param ThisVol         File System Volume
> +  @param FileName        The file to be read.
> +  @param BufferSize      The file buffer size
> +  @param Buffer          The file buffer
> +  @param ScanFs          Need Scan all FS
> +
> +  @retval EFI_SUCCESS    Read file successfully
> +  @retval EFI_NOT_FOUND  File not found
> +  @retval EFI_NO_MAPPING There is duplicated files found
> +**/
> +EFI_STATUS
> +ReadFileToBufferEx (
> +  IN OUT EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   **ThisVol,
> +  IN  CHAR16                               *FileName,
> +  OUT UINTN                                *BufferSize,
> +  OUT VOID                                 **Buffer,
> +  IN  BOOLEAN                              ScanFs
> +  )
> +{
> +  EFI_STATUS                        Status;
> +  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Vol;
> +  UINTN                             TempBufferSize;
> +  VOID                              *TempBuffer;
> +  UINTN                             NoHandles;
> +  EFI_HANDLE                        *HandleBuffer;
> +  UINTN                             Index;
> +
> +  //
> +  // Check parameters
> +  //
> +  if ((FileName == NULL) || (Buffer == NULL) || (ThisVol == NULL)) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  //
> +  // not scan fs
> +  //
> +  if (!ScanFs) {
> +    if (*ThisVol == NULL) {
> +      *ThisVol = GetMyVol ();
> +      if (*ThisVol == NULL) {
> +        return EFI_INVALID_PARAMETER;
> +      }
> +    }
> +    //
> +    // Read file directly from Vol
> +    //
> +    return ReadFileFromVol (*ThisVol, FileName, BufferSize, Buffer);
> +  }
> +
> +  //
> +  // need scan fs
> +  //
> +
> +  //
> +  // Get all Vol handle
> +  //
> +  Status = gBS->LocateHandleBuffer (
> +                   ByProtocol,
> +                   &gEfiSimpleFileSystemProtocolGuid,
> +                   NULL,
> +                   &NoHandles,
> +                   &HandleBuffer
> +                   );
> +  if (EFI_ERROR (Status) && (NoHandles == 0)) {
> +    return EFI_NOT_FOUND;
> +  }
> +
> +  //
> +  // Walk through each Vol
> +  //
> +  *ThisVol = NULL;
> +  *BufferSize = 0;
> +  *Buffer     = NULL;
> +  for (Index = 0; Index < NoHandles; Index++) {
> +    Status = gBS->HandleProtocol (
> +                    HandleBuffer[Index],
> +                    &gEfiSimpleFileSystemProtocolGuid,
> +                    (VOID **)&Vol
> +                    );
> +    if (EFI_ERROR(Status)) {
> +      continue;
> +    }
> +
> +    Status = ReadFileFromVol (Vol, FileName, &TempBufferSize, &TempBuffer);
> +    if (!EFI_ERROR (Status)) {
> +      //
> +      // Read file OK, check duplication
> +      //
> +      if (*ThisVol != NULL) {
> +        //
> +        // Find the duplicated file
> +        //
> +        gBS->FreePool (TempBuffer);
> +        gBS->FreePool (*Buffer);
> +        Print (L"Duplicated FileName found!\n");
> +        return EFI_NO_MAPPING;
> +      } else {
> +        //
> +        // Record value
> +        //
> +        *ThisVol = Vol;
> +        *BufferSize = TempBufferSize;
> +        *Buffer     = TempBuffer;
> +      }
> +    }
> +  }
> +
> +  //
> +  // Scan Fs done
> +  //
> +  if (*ThisVol == NULL) {
> +    return EFI_NOT_FOUND;
> +  }
> +
> +  //
> +  // Done
> +  //
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Read a file.
> +
> +  @param FileName        The file to be read.
> +  @param BufferSize      The file buffer size
> +  @param Buffer          The file buffer
> +
> +  @retval EFI_SUCCESS    Read file successfully
> +  @retval EFI_NOT_FOUND  File not found
> +**/
> +EFI_STATUS
> +ReadFileToBuffer (
> +  IN  CHAR16                               *FileName,
> +  OUT UINTN                                *BufferSize,
> +  OUT VOID                                 **Buffer
> +  )
> +{
> +  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Vol;
> +  Vol = NULL;
> +  return ReadFileToBufferEx(&Vol, FileName, BufferSize, Buffer, FALSE);
> +}
> +
> +/**
> +  Write a file.
> +
> +  @param FileName        The file to be written.
> +  @param BufferSize      The file buffer size
> +  @param Buffer          The file buffer
> +
> +  @retval EFI_SUCCESS    Write file successfully
> +**/
> +EFI_STATUS
> +WriteFileFromBuffer(
> +  IN  CHAR16                               *FileName,
> +  IN  UINTN                                BufferSize,
> +  IN  VOID                                 *Buffer
> +  )
> +{
> +  EFI_STATUS                        Status;
> +  EFI_FILE_HANDLE                   RootDir;
> +  EFI_FILE_HANDLE                   Handle;
> +  UINTN                             TempBufferSize;
> +  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Vol;
> +
> +  Vol = GetMyVol();
> +
> +  //
> +  // Open the root directory
> +  //
> +  Status = Vol->OpenVolume (Vol, &RootDir);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  //
> +  // Open the file
> +  //
> +  Status = RootDir->Open (
> +                      RootDir,
> +                      &Handle,
> +                      FileName,
> +                      EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE| EFI_FILE_MODE_CREATE,
> +                      0
> +                      );
> +  if (EFI_ERROR (Status)) {
> +    RootDir->Close (RootDir);
> +    return Status;
> +  }
> +
> +  //
> +  // Delete file
> +  //
> +  Status = Handle->Delete(Handle);
> +  if (EFI_ERROR(Status)) {
> +    return Status;
> +  }
> +
> +  //
> +  // Open the file again
> +  //
> +  Status = RootDir->Open (
> +                      RootDir,
> +                      &Handle,
> +                      FileName,
> +                      EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE| EFI_FILE_MODE_CREATE,
> +                      0
> +                      );
> +  if (EFI_ERROR (Status)) {
> +    RootDir->Close (RootDir);
> +    return Status;
> +  }
> +
> +  RootDir->Close (RootDir);
> +
> +  //
> +  // Write the file data from the buffer
> +  //
> +  TempBufferSize = BufferSize;
> +  Status = Handle->Write (
> +                     Handle,
> +                     &TempBufferSize,
> +                     Buffer
> +                     );
> +  if (EFI_ERROR (Status)) {
> +    Handle->Close (Handle);
> +    return Status;
> +  }
> +
> +  Handle->Close (Handle);
> +
> +  return EFI_SUCCESS;
> +}
> +
> diff --git a/MdeModulePkg/Application/CapsuleApp/CapsuleApp.c
> b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.c
> new file mode 100644
> index 0000000..6bb778a
> --- /dev/null
> +++ b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.c
> @@ -0,0 +1,853 @@
> +/** @file
> +  A shell application that triggers capsule update process.
> +
> +  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
> +  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.
> +
> +**/
> +
> +#include <Uefi.h>
> +#include <Library/BaseLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/UefiRuntimeServicesTableLib.h>
> +#include <Library/UefiLib.h>
> +#include <Library/PrintLib.h>
> +#include <Protocol/LoadedImage.h>
> +#include <Protocol/SimpleFileSystem.h>
> +#include <Protocol/GraphicsOutput.h>
> +#include <Guid/FileInfo.h>
> +#include <Guid/Gpt.h>
> +#include <Guid/GlobalVariable.h>
> +#include <Guid/CapsuleReport.h>
> +#include <Guid/SystemResourceTable.h>
> +#include <Guid/FmpCapsule.h>
> +#include <IndustryStandard/WindowsUxCapsule.h>
> +
> +#define CAPSULE_HEADER_SIZE  0x20
> +
> +#define NESTED_CAPSULE_HEADER_SIZE  SIZE_4KB
> +#define SYSTEM_FIRMWARE_FLAG 0x50000
> +#define DEVICE_FIRMWARE_FLAG 0x78010
> +
> +#define EFI_CAPSULE_FROM_FILE_DIR                           L"\\EFI\\UpdateCapsule\\"
> +#define EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED  0x0000000000000004
> +
> +#define MAJOR_VERSION   1
> +#define MINOR_VERSION   0
> +
> +#define MAX_CAPSULE_NUM 10
> +
> +extern UINTN  Argc;
> +extern CHAR16 **Argv;
> +
> +//
> +// Define how many block descriptors we want to test with.
> +//
> +UINTN  NumberOfDescriptors = 1;
> +UINTN  CapsuleFirstIndex;
> +UINTN  CapsuleLastIndex;
> +
> +/**
> +  Dump capsule information
> +
> +  @retval EFI_SUCCESS            The capsule information is dumped.
> +  @retval EFI_UNSUPPORTED        Input parameter is not valid.
> +**/
> +EFI_STATUS
> +DumpCapsule(
> +  VOID
> +  );
> +
> +/**
> +  Dump capsule status variable.
> +
> +  @retval EFI_SUCCESS            The capsule status variable is dumped.
> +  @retval EFI_UNSUPPORTED        Input parameter is not valid.
> +**/
> +EFI_STATUS
> +DmpCapsuleStatusVariable(
> +  VOID
> +  );
> +
> +/**
> +  Dump FMP protocol info.
> +**/
> +VOID
> +DumpFmpData(
> +  VOID
> +  );
> +
> +/**
> +  Dump ESRT info.
> +**/
> +VOID
> +DumpEsrtData(
> +  VOID
> +  );
> +
> +/**
> +  Read a file.
> +
> +  @param FileName        The file to be read.
> +  @param BufferSize      The file buffer size
> +  @param Buffer          The file buffer
> +
> +  @retval EFI_SUCCESS    Read file successfully
> +  @retval EFI_NOT_FOUND  File not found
> +**/
> +EFI_STATUS
> +ReadFileToBuffer(
> +  IN  CHAR16                               *FileName,
> +  OUT UINTN                                *BufferSize,
> +  OUT VOID                                 **Buffer
> +  );
> +
> +/**
> +  Write a file.
> +
> +  @param FileName        The file to be written.
> +  @param BufferSize      The file buffer size
> +  @param Buffer          The file buffer
> +
> +  @retval EFI_SUCCESS    Write file successfully
> +**/
> +EFI_STATUS
> +WriteFileFromBuffer(
> +  IN  CHAR16                               *FileName,
> +  IN  UINTN                                BufferSize,
> +  IN  VOID                                 *Buffer
> +  );
> +
> +/**
> +
> +  This function parse application ARG.
> +
> +  @return Status
> +**/
> +EFI_STATUS
> +GetArg (
> +  VOID
> +  );
> +
> +/**
> +  Create UX capsule.
> +
> +  @retval EFI_SUCCESS            The capsule header is appended.
> +  @retval EFI_UNSUPPORTED        Input parameter is not valid.
> +  @retval EFI_OUT_OF_RESOURCES   No enough resource to create UX capsule.
> +**/
> +EFI_STATUS
> +CreateBmpFmp(
> +  VOID
> +  )
> +{
> +  CHAR16                                        *OutputCapsuleName;
> +  VOID                                          *BmpBuffer;
> +  UINTN                                         FileSize;
> +  CHAR16                                        *BmpName;
> +  UINT8                                         *FullCapsuleBuffer;
> +  UINTN                                         FullCapsuleBufferSize;
> +  EFI_DISPLAY_CAPSULE                           *DisplayCapsule;
> +  EFI_STATUS                                    Status;
> +  EFI_GRAPHICS_OUTPUT_PROTOCOL                  *Gop;
> +
> +  Status = gBS->LocateProtocol(&gEfiGraphicsOutputProtocolGuid, NULL, (VOID **)&Gop);
> +  if (EFI_ERROR(Status)) {
> +    Print(L"CapsuleApp: NO GOP is found.\n");
> +    return EFI_UNSUPPORTED;
> +  }
> +  Print(L"Current GOP: Mode - %d, ", Gop->Mode->Mode);
> +  Print(L"HorizontalResolution - %d, ", Gop->Mode->Info->HorizontalResolution);
> +  Print(L"VerticalResolution - %d\n", Gop->Mode->Info->VerticalResolution);
> +  // HorizontalResolution >= BMP_IMAGE_HEADER.PixelWidth
> +  // VerticalResolution   >= BMP_IMAGE_HEADER.PixelHeight
> +
> +  if (Argc != 5) {
> +    Print(L"CapsuleApp: Invalid Parameter.\n");
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  if (StrCmp(Argv[3], L"-O") != 0) {
> +    Print(L"CapsuleApp: NO output capsule name.\n");
> +    return EFI_UNSUPPORTED;
> +  }
> +  OutputCapsuleName = Argv[4];
> +
> +  BmpBuffer = NULL;
> +  FileSize = 0;
> +  FullCapsuleBuffer = NULL;
> +
> +  BmpName = Argv[2];
> +  Status = ReadFileToBuffer(BmpName, &FileSize, &BmpBuffer);
> +  if (EFI_ERROR(Status)) {
> +    Print(L"CapsuleApp: BMP image (%s) is not found.\n", BmpName);
> +    goto Done;
> +  }
> +
> +  FullCapsuleBufferSize = sizeof(EFI_DISPLAY_CAPSULE) + FileSize;
> +  FullCapsuleBuffer = AllocatePool(FullCapsuleBufferSize);
> +  if (FullCapsuleBuffer == NULL) {
> +    Print(L"CapsuleApp: Capsule Buffer size (0x%x) too big.\n",
> FullCapsuleBufferSize);
> +    Status = EFI_OUT_OF_RESOURCES;
> +    goto Done;
> +  }
> +
> +  DisplayCapsule = (EFI_DISPLAY_CAPSULE *)FullCapsuleBuffer;
> +  CopyGuid(&DisplayCapsule->CapsuleHeader.CapsuleGuid, &gWindowsUxCapsuleGuid);
> +  DisplayCapsule->CapsuleHeader.HeaderSize = sizeof(DisplayCapsule->CapsuleHeader);
> +  DisplayCapsule->CapsuleHeader.Flags = CAPSULE_FLAGS_PERSIST_ACROSS_RESET;
> +  DisplayCapsule->CapsuleHeader.CapsuleImageSize = (UINT32)FullCapsuleBufferSize;
> +
> +  DisplayCapsule->ImagePayload.Version = 1;
> +  DisplayCapsule->ImagePayload.Checksum = 0;
> +  DisplayCapsule->ImagePayload.ImageType = 0; // BMP
> +  DisplayCapsule->ImagePayload.Reserved = 0;
> +  DisplayCapsule->ImagePayload.Mode = Gop->Mode->Mode;
> +  DisplayCapsule->ImagePayload.OffsetX = 0;
> +  DisplayCapsule->ImagePayload.OffsetY = 0;
> +
> +  CopyMem((DisplayCapsule + 1), BmpBuffer, FileSize);
> +
> +  DisplayCapsule->ImagePayload.Checksum = CalculateCheckSum8(FullCapsuleBuffer,
> FullCapsuleBufferSize);
> +
> +  Status = WriteFileFromBuffer(OutputCapsuleName, FullCapsuleBufferSize,
> FullCapsuleBuffer);
> +  Print(L"CapsuleApp: Write %s %r\n", OutputCapsuleName, Status);
> +
> +Done:
> +  if (BmpBuffer != NULL) {
> +    FreePool(BmpBuffer);
> +  }
> +
> +  if (FullCapsuleBuffer != NULL) {
> +    FreePool(FullCapsuleBuffer);
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  Get ImageTypeId in the FMP capsule header.
> +
> +  @param CapsuleHeader  The FMP capsule image header.
> +
> +  @return ImageTypeId
> +**/
> +EFI_GUID *
> +GetCapsuleImageTypeId(
> +  IN EFI_CAPSULE_HEADER                            *CapsuleHeader
> +  )
> +{
> +  EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER       *FmpCapsuleHeader;
> +  UINT64                                       *ItemOffsetList;
> +  EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader;
> +
> +  FmpCapsuleHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *)((UINT8 *)CapsuleHeader
> + CapsuleHeader->HeaderSize);
> +  ItemOffsetList = (UINT64 *)(FmpCapsuleHeader + 1);
> +  if (FmpCapsuleHeader->PayloadItemCount == 0) {
> +    return NULL;
> +  }
> +  ImageHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *)((UINT8
> *)FmpCapsuleHeader + ItemOffsetList[FmpCapsuleHeader->EmbeddedDriverCount]);
> +  return &ImageHeader->UpdateImageTypeId;
> +}
> +
> +/**
> +  Get ESRT FwType according to ImageTypeId
> +
> +  @param  ImageTypeId   ImageTypeId of an FMP capsule.
> +
> +  @return ESRT FwType
> +**/
> +UINT32
> +GetEsrtFwType(
> +  IN  EFI_GUID                                      *ImageTypeId
> +  )
> +{
> +  EFI_STATUS                 Status;
> +  EFI_SYSTEM_RESOURCE_TABLE  *Esrt;
> +  EFI_SYSTEM_RESOURCE_ENTRY  *EsrtEntry;
> +  UINTN                      Index;
> +
> +  //
> +  // Check ESRT
> +  //
> +  Status = EfiGetSystemConfigurationTable(&gEfiSystemResourceTableGuid, (VOID
> **)&Esrt);
> +  if (!EFI_ERROR(Status)) {
> +    EsrtEntry = (VOID *)(Esrt + 1);
> +    for (Index = 0; Index < Esrt->FwResourceCount; Index++, EsrtEntry++) {
> +      if (CompareGuid(&EsrtEntry->FwClass, ImageTypeId)) {
> +        return EsrtEntry->FwType;
> +      }
> +    }
> +  }
> +
> +  return ESRT_FW_TYPE_UNKNOWN;
> +}
> +
> +/**
> +  Append a capsule header on top of current image.
> +  This function follows Windows UEFI Firmware Update Platform document.
> +
> +  @retval EFI_SUCCESS            The capsule header is appended.
> +  @retval EFI_UNSUPPORTED        Input parameter is not valid.
> +  @retval EFI_OUT_OF_RESOURCES   No enough resource to append capsule header.
> +**/
> +EFI_STATUS
> +CreateNestedFmp(
> +  VOID
> +  )
> +{
> +  CHAR16                                        *OutputCapsuleName;
> +  VOID                                          *CapsuleBuffer;
> +  UINTN                                         FileSize;
> +  CHAR16                                        *CapsuleName;
> +  UINT8                                         *FullCapsuleBuffer;
> +  UINTN                                         FullCapsuleBufferSize;
> +  EFI_CAPSULE_HEADER                            *NestedCapsuleHeader;
> +  EFI_GUID                                      *ImageTypeId;
> +  UINT32                                        FwType;
> +  EFI_STATUS                                    Status;
> +
> +  if (Argc != 5) {
> +    Print(L"CapsuleApp: Invalid Parameter.\n");
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  if (StrCmp(Argv[3], L"-O") != 0) {
> +    Print(L"CapsuleApp: NO output capsule name.\n");
> +    return EFI_UNSUPPORTED;
> +  }
> +  OutputCapsuleName = Argv[4];
> +
> +  CapsuleBuffer = NULL;
> +  FileSize = 0;
> +  FullCapsuleBuffer = NULL;
> +
> +  CapsuleName = Argv[2];
> +  Status = ReadFileToBuffer(CapsuleName, &FileSize, &CapsuleBuffer);
> +  if (EFI_ERROR(Status)) {
> +    Print(L"CapsuleApp: Capsule image (%s) is not found.\n", CapsuleName);
> +    goto Done;
> +  }
> +
> +  ImageTypeId = GetCapsuleImageTypeId(CapsuleBuffer);
> +  if (ImageTypeId == NULL) {
> +    Print(L"CapsuleApp: Capsule ImageTypeId is not found.\n");
> +    goto Done;
> +  }
> +  FwType = GetEsrtFwType(ImageTypeId);
> +  if ((FwType != ESRT_FW_TYPE_SYSTEMFIRMWARE) && (FwType !=
> ESRT_FW_TYPE_DEVICEFIRMWARE)) {
> +    Print(L"CapsuleApp: Capsule FwType is invalid.\n");
> +    goto Done;
> +  }
> +
> +  FullCapsuleBufferSize = NESTED_CAPSULE_HEADER_SIZE + FileSize;
> +  FullCapsuleBuffer = AllocatePool(FullCapsuleBufferSize);
> +  if (FullCapsuleBuffer == NULL) {
> +    Print(L"CapsuleApp: Capsule Buffer size (0x%x) too big.\n",
> FullCapsuleBufferSize);
> +    Status = EFI_OUT_OF_RESOURCES;
> +    goto Done;
> +  }
> +
> +  NestedCapsuleHeader = (EFI_CAPSULE_HEADER *)FullCapsuleBuffer;
> +  ZeroMem(NestedCapsuleHeader, NESTED_CAPSULE_HEADER_SIZE);
> +  CopyGuid(&NestedCapsuleHeader->CapsuleGuid, ImageTypeId);
> +  NestedCapsuleHeader->HeaderSize = NESTED_CAPSULE_HEADER_SIZE;
> +  NestedCapsuleHeader->Flags = (FwType == ESRT_FW_TYPE_DEVICEFIRMWARE) ?
> SYSTEM_FIRMWARE_FLAG : DEVICE_FIRMWARE_FLAG;
> +  NestedCapsuleHeader->CapsuleImageSize = (UINT32)FullCapsuleBufferSize;
> +
> +  CopyMem((UINT8 *)NestedCapsuleHeader + NestedCapsuleHeader->HeaderSize,
> CapsuleBuffer, FileSize);
> +
> +  Status = WriteFileFromBuffer(OutputCapsuleName, FullCapsuleBufferSize,
> FullCapsuleBuffer);
> +  Print(L"CapsuleApp: Write %s %r\n", OutputCapsuleName, Status);
> +
> +Done:
> +  if (CapsuleBuffer != NULL) {
> +    FreePool(CapsuleBuffer);
> +  }
> +
> +  if (FullCapsuleBuffer != NULL) {
> +    FreePool(FullCapsuleBuffer);
> +  }
> +
> +  return Status;
> +}
> +
> +
> +/**
> +  Clear capsule status variable.
> +
> +  @retval EFI_SUCCESS            The capsule status variable is cleared.
> +**/
> +EFI_STATUS
> +ClearCapsuleStatusVariable(
> +  VOID
> +  )
> +{
> +  EFI_STATUS                          Status;
> +  UINT32                              Index;
> +  CHAR16                              CapsuleVarName[20];
> +  CHAR16                              *TempVarName;
> +
> +  StrCpyS (CapsuleVarName, sizeof(CapsuleVarName)/sizeof(CapsuleVarName[0]),
> L"Capsule");
> +  TempVarName = CapsuleVarName + StrLen (CapsuleVarName);
> +  Index = 0;
> +
> +  while (TRUE) {
> +    UnicodeSPrint (TempVarName, 5 * sizeof(CHAR16), L"%04x", Index);
> +
> +    Status = gRT->SetVariable (
> +                    CapsuleVarName,
> +                    &gEfiCapsuleReportGuid,
> +                    EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS |
> EFI_VARIABLE_BOOTSERVICE_ACCESS,
> +                    0,
> +                    (VOID *)NULL
> +                    );
> +    if (EFI_ERROR(Status)) {
> +      //
> +      // There is no capsule variables, quit
> +      //
> +      break;
> +    }
> +
> +    Index++;
> +    if (Index > 0xFFFF) {
> +      break;
> +    }
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Build Gather list for a list of capsule images.
> +
> +  @param[in]  CapsuleBuffer    An array of pointer to capsule images
> +  @param[in]  FileSize         An array of UINTN to capsule images size
> +  @param[in]  CapsuleNum       The count of capsule images
> +  @param[out] BlockDescriptors The block descriptors for the capsule images
> +
> +  @retval EFI_SUCCESS The block descriptors for the capsule images are constructed.
> +**/
> +EFI_STATUS
> +BuildGatherList(
> +  IN VOID                          **CapsuleBuffer,
> +  IN UINTN                         *FileSize,
> +  IN UINTN                         CapsuleNum,
> +  OUT EFI_CAPSULE_BLOCK_DESCRIPTOR **BlockDescriptors
> +  )
> +{
> +  EFI_STATUS                    Status;
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR  *BlockDescriptors1;
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR  *BlockDescriptors2;
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR  *BlockDescriptorPre;
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR  *BlockDescriptorsHeader;
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR  *TempBlockPtr;
> +  UINT8                         *TempDataPtr;
> +  UINTN                         SizeLeft;
> +  UINTN                         Size;
> +  INT32                         Count;
> +  INT32                         Number;
> +  UINTN                         Index;
> +
> +  TempBlockPtr           = NULL;
> +  BlockDescriptors1      = NULL;
> +  BlockDescriptors2      = NULL;
> +  BlockDescriptorPre     = NULL;
> +  BlockDescriptorsHeader = NULL;
> +
> +  for (Index = 0; Index < CapsuleNum; Index++) {
> +    //
> +    // Allocate memory for the descriptors.
> +    //
> +    if (NumberOfDescriptors == 1) {
> +      Count = 2;
> +    } else {
> +      Count = (INT32)(NumberOfDescriptors + 2) / 2;
> +    }
> +
> +    Size               = Count * sizeof (EFI_CAPSULE_BLOCK_DESCRIPTOR);
> +    BlockDescriptors1  = AllocateRuntimeZeroPool (Size);
> +    if (BlockDescriptors1 == NULL) {
> +      Print (L"CapsuleApp: failed to allocate memory for descriptors\n");
> +      Status = EFI_OUT_OF_RESOURCES;
> +      goto ERREXIT;
> +    } else {
> +      Print (L"CapsuleApp: creating capsule descriptors at 0x%X\n", (UINTN)
> BlockDescriptors1);
> +      Print (L"CapsuleApp: capsule data starts          at 0x%X with size 0x%X\n",
> (UINTN) CapsuleBuffer, FileSize);
> +    }
> +
> +    //
> +    // Record descirptor header
> +    //
> +    if (Index == 0) {
> +      BlockDescriptorsHeader = BlockDescriptors1;
> +    }
> +
> +    if (BlockDescriptorPre != NULL) {
> +      BlockDescriptorPre->Union.ContinuationPointer = (UINTN) BlockDescriptors1;
> +      BlockDescriptorPre->Length = 0;
> +    }
> +
> +    //
> +    // Fill them in
> +    //
> +    TempBlockPtr  = BlockDescriptors1;
> +    TempDataPtr   = CapsuleBuffer[Index];
> +    SizeLeft      = FileSize[Index];
> +    for (Number = 0; (Number < Count - 1) && (SizeLeft != 0); Number++) {
> +      //
> +      // Divide remaining data in half
> +      //
> +      if (NumberOfDescriptors != 1) {
> +        if (SizeLeft == 1) {
> +          Size = 1;
> +        } else {
> +          Size = SizeLeft / 2;
> +        }
> +      } else {
> +        Size = SizeLeft;
> +      }
> +      TempBlockPtr->Union.DataBlock    = (UINTN)TempDataPtr;
> +      TempBlockPtr->Length  = Size;
> +      Print (L"CapsuleApp: capsule block/size              0x%X/0x%X\n", (UINTN)
> TempDataPtr, Size);
> +      SizeLeft -= Size;
> +      TempDataPtr += Size;
> +      TempBlockPtr++;
> +    }
> +
> +    //
> +    // Allocate the second list, point the first block's last entry to point
> +    // to this one, and fill this one in. Worst case is that the previous
> +    // list only had one element that pointed here, so we need at least two
> +    // elements -- one to point to all the data, another to terminate the list.
> +    //
> +    if ((NumberOfDescriptors != 1) && (SizeLeft != 0)) {
> +      Count = (INT32)(NumberOfDescriptors + 2) - Count;
> +      if (Count == 1) {
> +        Count++;
> +      }
> +
> +      Size              = Count * sizeof (EFI_CAPSULE_BLOCK_DESCRIPTOR);
> +      BlockDescriptors2 = AllocateRuntimeZeroPool (Size);
> +      if (BlockDescriptors2 == NULL) {
> +        Print (L"CapsuleApp: failed to allocate memory for descriptors\n");
> +        Status = EFI_OUT_OF_RESOURCES;
> +        goto ERREXIT;
> +      }
> +
> +      //
> +      // Point the first list's last element to point to this second list.
> +      //
> +      TempBlockPtr->Union.ContinuationPointer   = (UINTN) BlockDescriptors2;
> +
> +      TempBlockPtr->Length  = 0;
> +      TempBlockPtr = BlockDescriptors2;
> +      for (Number = 0; Number < Count - 1; Number++) {
> +        //
> +        // If second-to-last one, then dump rest to this element
> +        //
> +        if (Number == (Count - 2)) {
> +          Size = SizeLeft;
> +        } else {
> +          //
> +          // Divide remaining data in half
> +          //
> +          if (SizeLeft == 1) {
> +            Size = 1;
> +          } else {
> +            Size = SizeLeft / 2;
> +          }
> +        }
> +
> +        TempBlockPtr->Union.DataBlock    = (UINTN)TempDataPtr;
> +        TempBlockPtr->Length  = Size;
> +        Print (L"CapsuleApp: capsule block/size              0x%X/0x%X\n", (UINTN)
> TempDataPtr, Size);
> +        SizeLeft -= Size;
> +        TempDataPtr += Size;
> +        TempBlockPtr++;
> +        if (SizeLeft == 0) {
> +          break;
> +        }
> +      }
> +    }
> +
> +    BlockDescriptorPre = TempBlockPtr;
> +    BlockDescriptors1  = NULL;
> +  }
> +
> +  //
> +  // Null-terminate.
> +  //
> +  if (TempBlockPtr != NULL) {
> +    TempBlockPtr->Union.ContinuationPointer    = (UINTN)NULL;
> +    TempBlockPtr->Length  = 0;
> +    *BlockDescriptors = BlockDescriptorsHeader;
> +  }
> +
> +  return EFI_SUCCESS;
> +
> +ERREXIT:
> +  if (BlockDescriptors1 != NULL) {
> +    FreePool(BlockDescriptors1);
> +  }
> +
> +  if (BlockDescriptors2 != NULL) {
> +    FreePool(BlockDescriptors2);
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  Clear the Gather list for a list of capsule images.
> +
> +  @param[in]  BlockDescriptors The block descriptors for the capsule images
> +  @param[in]  CapsuleNum       The count of capsule images
> +**/
> +VOID
> +CleanGatherList(
> +  IN EFI_CAPSULE_BLOCK_DESCRIPTOR   *BlockDescriptors,
> +  IN UINTN                          CapsuleNum
> +  )
> +{
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR   *TempBlockPtr;
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR   *TempBlockPtr1;
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR   *TempBlockPtr2;
> +  UINTN                          Index;
> +
> +  if (BlockDescriptors != NULL) {
> +    TempBlockPtr1 = BlockDescriptors;
> +    while (1){
> +      TempBlockPtr = TempBlockPtr1;
> +      for (Index = 0; Index < CapsuleNum; Index++) {
> +        if (TempBlockPtr[Index].Length == 0) {
> +          break;
> +        }
> +      }
> +
> +      if (TempBlockPtr[Index].Union.ContinuationPointer == (UINTN)NULL) {
> +        break;
> +      }
> +
> +      TempBlockPtr2 = (VOID *) ((UINTN) TempBlockPtr->Union.ContinuationPointer);
> +      FreePool(TempBlockPtr1);
> +      TempBlockPtr1 = TempBlockPtr2;
> +    }
> +  }
> +}
> +
> +/**
> +  Print APP usage.
> +**/
> +VOID
> +PrintUsage (
> +  VOID
> +  )
> +{
> +  Print(L"CapsuleApp:  usage\n");
> +  Print(L"  CapsuleApp <Capsule...> [-NR]\n");
> +  Print(L"  CapsuleApp -S\n");
> +  Print(L"  CapsuleApp -C\n");
> +  Print(L"  CapsuleApp -P\n");
> +  Print(L"  CapsuleApp -E\n");
> +  Print(L"  CapsuleApp -G <BMP> -O <Capsule>\n");
> +  Print(L"  CapsuleApp -N <Capsule> -O <NestedCapsule>\n");
> +  Print(L"  CapsuleApp -D|-DS <Capsule>\n");
> +  Print(L"Parameter:\n");
> +  Print(L"  -NR: No Reset.\n");
> +  Print(L"  -S:  Dump capsule status.\n");
> +  Print(L"  -C:  Clear capsule status.\n");
> +  Print(L"  -P:  Dump FMP protocol info.\n");
> +  Print(L"  -E:  Dump ESRT table info.\n");
> +  Print(L"  -G:  Input BMP file name\n");
> +  Print(L"  -N:  Append Capsule Header accroding to Windows Firmware Update\n");
> +  Print(L"  -O:  Output Capsule file name\n");
> +  Print(L"  -D:  Dump Capsule\n");
> +}
> +
> +/**
> +  Update Capsule image.
> +
> +  @param[in]  ImageHandle     The image handle.
> +  @param[in]  SystemTable     The system table.
> +
> +  @retval EFI_SUCCESS            Command completed successfully.
> +  @retval EFI_INVALID_PARAMETER  Command usage error.
> +  @retval EFI_NOT_FOUND          The input file can't be found.
> +**/
> +EFI_STATUS
> +EFIAPI
> +UefiMain (
> +  IN EFI_HANDLE        ImageHandle,
> +  IN EFI_SYSTEM_TABLE  *SystemTable
> +  )
> +{
> +  EFI_STATUS                    Status;
> +  UINTN                         FileSize[MAX_CAPSULE_NUM];
> +  VOID                          *CapsuleBuffer[MAX_CAPSULE_NUM];
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR  *BlockDescriptors;
> +  EFI_CAPSULE_HEADER             *CapsuleHeaderArray[MAX_CAPSULE_NUM + 1];
> +  UINT64                         MaxCapsuleSize;
> +  EFI_RESET_TYPE                 ResetType;
> +  BOOLEAN                        NeedReset;
> +  BOOLEAN                        NoReset;
> +  CHAR16                         *CapsuleName;
> +  UINTN                          CapsuleNum;
> +  UINTN                          Index;
> +
> +  Status = GetArg();
> +  if (EFI_ERROR(Status)) {
> +    Print(L"Please use UEFI SHELL to run this application!\n", Status);
> +    return Status;
> +  }
> +  if (Argc < 2) {
> +    PrintUsage();
> +    return EFI_INVALID_PARAMETER;
> +  }
> +  if (StrCmp(Argv[1], L"-D") == 0) {
> +    Status = DumpCapsule();
> +    return Status;
> +  }
> +  if (StrCmp(Argv[1], L"-G") == 0) {
> +    Status = CreateBmpFmp();
> +    return Status;
> +  }
> +  if (StrCmp(Argv[1], L"-N") == 0) {
> +    Status = CreateNestedFmp();
> +    return Status;
> +  }
> +  if (StrCmp(Argv[1], L"-S") == 0) {
> +    Status = DmpCapsuleStatusVariable();
> +    return EFI_SUCCESS;
> +  }
> +  if (StrCmp(Argv[1], L"-C") == 0) {
> +    Status = ClearCapsuleStatusVariable();
> +    return Status;
> +  }
> +  if (StrCmp(Argv[1], L"-P") == 0) {
> +    DumpFmpData();
> +    return EFI_SUCCESS;
> +  }
> +  if (StrCmp(Argv[1], L"-E") == 0) {
> +    DumpEsrtData();
> +    return EFI_SUCCESS;
> +  }
> +  CapsuleFirstIndex = 1;
> +  if (StrCmp(Argv[Argc - 1], L"-NR") == 0) {
> +    NoReset = TRUE;
> +    CapsuleLastIndex = Argc - 2;
> +  } else {
> +    NoReset = FALSE;
> +    CapsuleLastIndex = Argc - 1;
> +  }
> +  CapsuleNum = CapsuleLastIndex - CapsuleFirstIndex + 1;
> +
> +  if (CapsuleFirstIndex > CapsuleLastIndex) {
> +    Print(L"CapsuleApp: NO capsule image.\n");
> +    return EFI_UNSUPPORTED;
> +  }
> +  if (CapsuleNum > MAX_CAPSULE_NUM) {
> +    Print(L"CapsuleApp: Too many capsule images.\n");
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  ZeroMem(&CapsuleBuffer, sizeof(CapsuleBuffer));
> +  ZeroMem(&FileSize, sizeof(FileSize));
> +  BlockDescriptors = NULL;
> +
> +  for (Index = 0; Index < CapsuleNum; Index++) {
> +    CapsuleName = Argv[CapsuleFirstIndex + Index];
> +    Status = ReadFileToBuffer(CapsuleName, &FileSize[Index], &CapsuleBuffer[Index]);
> +    if (EFI_ERROR(Status)) {
> +      Print(L"CapsuleApp: capsule image (%s) is not found.\n", CapsuleName);
> +      goto Done;
> +    }
> +  }
> +
> +  //
> +  // Every capsule use 2 descriptor 1 for data 1 for end
> +  //
> +  Status = BuildGatherList(CapsuleBuffer, FileSize, CapsuleNum, &BlockDescriptors);
> +  if (EFI_ERROR(Status)) {
> +    goto Done;
> +  }
> +
> +  //
> +  // Call the runtime service capsule.
> +  //
> +  NeedReset = FALSE;
> +  for (Index = 0; Index < CapsuleNum; Index++) {
> +    CapsuleHeaderArray[Index] = (EFI_CAPSULE_HEADER *) CapsuleBuffer[Index];
> +    if ((CapsuleHeaderArray[Index]->Flags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET) != 0)
> {
> +      NeedReset = TRUE;
> +    }
> +  }
> +  CapsuleHeaderArray[CapsuleNum] = NULL;
> +  if (NoReset) {
> +    NeedReset = FALSE;
> +  }
> +
> +  //
> +  // Inquire platform capability of UpdateCapsule.
> +  //
> +  Status = gRT->QueryCapsuleCapabilities (CapsuleHeaderArray, CapsuleNum,
> &MaxCapsuleSize, &ResetType);
> +  if (EFI_ERROR(Status)) {
> +    Print (L"CapsuleApp: failed to query capsule capability - %r\n", Status);
> +    goto Done;
> +  }
> +
> +  for (Index = 0; Index < CapsuleNum; Index++) {
> +    if (FileSize[Index] > MaxCapsuleSize) {
> +      Print (L"CapsuleApp: capsule is too large to update, %ld is allowed\n",
> MaxCapsuleSize);
> +      Status = EFI_UNSUPPORTED;
> +      goto Done;
> +    }
> +  }
> +
> +  //
> +  // Check whether the input capsule image has the flag of persist across system
> reset.
> +  //
> +  if (NeedReset) {
> +    Status = gRT->UpdateCapsule(CapsuleHeaderArray,CapsuleNum,(UINTN)
> BlockDescriptors);
> +    if (Status != EFI_SUCCESS) {
> +      Print (L"CapsuleApp: failed to update capsule - %r\n", Status);
> +      goto Done;
> +    }
> +    //
> +    // For capsule who has reset flag, after calling UpdateCapsule service,triger a
> +    // system reset to process capsule persist across a system reset.
> +    //
> +    gRT->ResetSystem (ResetType, EFI_SUCCESS, 0, NULL);
> +  } else {
> +    //
> +    // For capsule who has no reset flag, only call UpdateCapsule Service without a
> +    // system reset. The service will process the capsule immediately.
> +    //
> +    Status = gRT->UpdateCapsule (CapsuleHeaderArray,CapsuleNum,(UINTN)
> BlockDescriptors);
> +    if (Status != EFI_SUCCESS) {
> +      Print (L"CapsuleApp: failed to update capsule - %r\n", Status);
> +    }
> +  }
> +
> +  Status = EFI_SUCCESS;
> +
> +Done:
> +  for (Index = 0; Index < CapsuleNum; Index++) {
> +    if (CapsuleBuffer[Index] != NULL) {
> +      FreePool (CapsuleBuffer[Index]);
> +    }
> +  }
> +
> +  CleanGatherList(BlockDescriptors, CapsuleNum);
> +
> +  return Status;
> +}
> diff --git a/MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf
> b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf
> new file mode 100644
> index 0000000..2084e5f
> --- /dev/null
> +++ b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf
> @@ -0,0 +1,71 @@
> +##  @file
> +#  A shell application that triggers capsule update process.
> +#
> +# This application can trigger capsule update process. It can also
> +# generate capsule image, or dump capsule variable information.
> +#
> +#  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
> +#  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]
> +  INF_VERSION                    = 0x00010006
> +  BASE_NAME                      = CapsuleApp
> +  MODULE_UNI_FILE                = CapsuleApp.uni
> +  FILE_GUID                      = 4CEF31DA-8682-4274-9CC4-AEE7516A5E7B
> +  MODULE_TYPE                    = UEFI_APPLICATION
> +  VERSION_STRING                 = 1.0
> +  ENTRY_POINT                    = UefiMain
> +
> +#
> +# The following information is for reference only and not required by the build tools.
> +#
> +#  VALID_ARCHITECTURES           = IA32 X64
> +#
> +
> +[Sources]
> +  CapsuleApp.c
> +  CapsuleDump.c
> +  AppSupport.c
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +
> +[Guids]
> +  gEfiFileInfoGuid
> +  gEfiPartTypeSystemPartGuid
> +  gEfiGlobalVariableGuid
> +  gEfiCapsuleReportGuid
> +  gEfiFmpCapsuleGuid
> +  gWindowsUxCapsuleGuid
> +  gEfiCertTypeRsa2048Sha256Guid
> +  gEfiCertPkcs7Guid
> +  gEfiSystemResourceTableGuid
> +
> +[Protocols]
> +  gEfiLoadedImageProtocolGuid
> +  gEfiSimpleFileSystemProtocolGuid
> +  gEfiGraphicsOutputProtocolGuid
> +  gEfiFirmwareManagementProtocolGuid
> +  gEfiShellParametersProtocolGuid
> +
> +[LibraryClasses]
> +  BaseLib
> +  UefiApplicationEntryPoint
> +  DebugLib
> +  MemoryAllocationLib
> +  UefiBootServicesTableLib
> +  UefiRuntimeServicesTableLib
> +  UefiLib
> +  PrintLib
> +
> +[UserExtensions.TianoCore."ExtraFiles"]
> +  CapsuleAppExtra.uni
> diff --git a/MdeModulePkg/Application/CapsuleApp/CapsuleApp.uni
> b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.uni
> new file mode 100644
> index 0000000..54d6e12
> --- /dev/null
> +++ b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.uni
> @@ -0,0 +1,22 @@
> +// /** @file
> +// A shell application that triggers capsule update process.
> +//
> +// This application can trigger capsule update process. It can also
> +// generate capsule image, or dump capsule variable information.
> +//
> +// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
> +//
> +// 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.
> +//
> +// **/
> +
> +
> +#string STR_MODULE_ABSTRACT             #language en-US "A shell application that
> triggers capsule update process."
> +
> +#string STR_MODULE_DESCRIPTION          #language en-US "This application can trigger
> capsule update process. It can also generate capsule image, or dump capsule variable
> information."
> +
> diff --git a/MdeModulePkg/Application/CapsuleApp/CapsuleAppExtra.uni
> b/MdeModulePkg/Application/CapsuleApp/CapsuleAppExtra.uni
> new file mode 100644
> index 0000000..b5a8840
> --- /dev/null
> +++ b/MdeModulePkg/Application/CapsuleApp/CapsuleAppExtra.uni
> @@ -0,0 +1,19 @@
> +// /** @file
> +// CapsuleApp Localized Strings and Content
> +//
> +// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
> +//
> +// 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.
> +//
> +// **/
> +
> +#string STR_PROPERTIES_MODULE_NAME
> +#language en-US
> +"Capsule Application"
> +
> +
> diff --git a/MdeModulePkg/Application/CapsuleApp/CapsuleDump.c
> b/MdeModulePkg/Application/CapsuleApp/CapsuleDump.c
> new file mode 100644
> index 0000000..b383fe1
> --- /dev/null
> +++ b/MdeModulePkg/Application/CapsuleApp/CapsuleDump.c
> @@ -0,0 +1,740 @@
> +/** @file
> +  Dump Capsule image information.
> +
> +  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
> +  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.
> +
> +**/
> +
> +#include <PiDxe.h>
> +#include <Library/BaseLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/UefiRuntimeServicesTableLib.h>
> +#include <Library/UefiLib.h>
> +#include <Library/PrintLib.h>
> +#include <Protocol/FirmwareManagement.h>
> +#include <Guid/ImageAuthentication.h>
> +#include <Guid/CapsuleReport.h>
> +#include <Guid/SystemResourceTable.h>
> +#include <Guid/FmpCapsule.h>
> +#include <IndustryStandard/WindowsUxCapsule.h>
> +
> +/**
> +  Read a file.
> +
> +  @param FileName        The file to be read.
> +  @param BufferSize      The file buffer size
> +  @param Buffer          The file buffer
> +
> +  @retval EFI_SUCCESS    Read file successfully
> +  @retval EFI_NOT_FOUND  File not found
> +**/
> +EFI_STATUS
> +ReadFileToBuffer(
> +  IN  CHAR16                               *FileName,
> +  OUT UINTN                                *BufferSize,
> +  OUT VOID                                 **Buffer
> +  );
> +
> +extern UINTN  Argc;
> +extern CHAR16 *Argv[];
> +
> +/**
> +  Dump UX capsule information.
> +
> +  @param CapsuleHeader      The UX capsule header
> +**/
> +VOID
> +DumpUxCapsule(
> +  IN EFI_CAPSULE_HEADER  *CapsuleHeader
> +  )
> +{
> +  EFI_DISPLAY_CAPSULE                           *DisplayCapsule;
> +  DisplayCapsule = (EFI_DISPLAY_CAPSULE *)CapsuleHeader;
> +  Print(L"[UxCapusule]\n");
> +  Print(L"CapsuleHeader:\n");
> +  Print(L"  CapsuleGuid      - %g\n", &DisplayCapsule->CapsuleHeader.CapsuleGuid);
> +  Print(L"  HeaderSize       - 0x%x\n", DisplayCapsule->CapsuleHeader.HeaderSize);
> +  Print(L"  Flags            - 0x%x\n", DisplayCapsule->CapsuleHeader.Flags);
> +  Print(L"  CapsuleImageSize - 0x%x\n", DisplayCapsule-
> >CapsuleHeader.CapsuleImageSize);
> +  Print(L"ImagePayload:\n");
> +  Print(L"  Version          - 0x%x\n", DisplayCapsule->ImagePayload.Version);
> +  Print(L"  Checksum         - 0x%x\n", DisplayCapsule->ImagePayload.Checksum);
> +  Print(L"  ImageType        - 0x%x\n", DisplayCapsule->ImagePayload.ImageType);
> +  Print(L"  Mode             - 0x%x\n", DisplayCapsule->ImagePayload.Mode);
> +  Print(L"  OffsetX          - 0x%x\n", DisplayCapsule->ImagePayload.OffsetX);
> +  Print(L"  OffsetY          - 0x%x\n", DisplayCapsule->ImagePayload.OffsetY);
> +}
> +
> +/**
> +  Dump FMP image authentication information.
> +
> +  @param Image      The FMP capsule image
> +  @param ImageSize  The size of the FMP capsule image in bytes.
> +
> +  @return the size of FMP authentication.
> +**/
> +UINTN
> +DumpImageAuthentication(
> +  IN VOID   *Image,
> +  IN UINTN  ImageSize
> +  )
> +{
> +  EFI_FIRMWARE_IMAGE_AUTHENTICATION             *ImageAuthentication;
> +
> +  ImageAuthentication = Image;
> +  if (CompareGuid(&ImageAuthentication->AuthInfo.CertType, &gEfiCertPkcs7Guid) ||
> +      CompareGuid(&ImageAuthentication->AuthInfo.CertType,
> &gEfiCertTypeRsa2048Sha256Guid)) {
> +    Print(L"[ImageAuthentication]\n");
> +    Print(L"  MonotonicCount   - 0x%lx\n", ImageAuthentication->MonotonicCount);
> +    Print(L"WIN_CERTIFICATE:\n");
> +    Print(L"  dwLength         - 0x%x\n", ImageAuthentication->AuthInfo.Hdr.dwLength);
> +    Print(L"  wRevision        - 0x%x\n", ImageAuthentication-
> >AuthInfo.Hdr.wRevision);
> +    Print(L"  wCertificateType - 0x%x\n", ImageAuthentication-
> >AuthInfo.Hdr.wCertificateType);
> +    Print(L"  CertType         - %g\n", &ImageAuthentication->AuthInfo.CertType);
> +    return sizeof(ImageAuthentication->MonotonicCount) + ImageAuthentication-
> >AuthInfo.Hdr.dwLength;
> +  } else {
> +    return 0;
> +  }
> +}
> +
> +/**
> +  Dump a non-nested FMP capsule.
> +
> +  @param  CapsuleHeader  A pointer to CapsuleHeader
> +**/
> +VOID
> +DumpFmpCapsule(
> +  IN EFI_CAPSULE_HEADER  *CapsuleHeader
> +  )
> +{
> +  EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER        *FmpCapsuleHeader;
> +  UINT64                                        *ItemOffsetList;
> +  UINTN                                         Index;
> +  UINTN                                         Count;
> +  EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER  *FmpImageHeader;
> +
> +  Print(L"[FmpCapusule]\n");
> +  Print(L"CapsuleHeader:\n");
> +  Print(L"  CapsuleGuid      - %g\n", &CapsuleHeader->CapsuleGuid);
> +  Print(L"  HeaderSize       - 0x%x\n", CapsuleHeader->HeaderSize);
> +  Print(L"  Flags            - 0x%x\n", CapsuleHeader->Flags);
> +  Print(L"  CapsuleImageSize - 0x%x\n", CapsuleHeader->CapsuleImageSize);
> +
> +  FmpCapsuleHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *)((UINT8 *)CapsuleHeader
> + CapsuleHeader->HeaderSize);
> +  ItemOffsetList = (UINT64 *)(FmpCapsuleHeader + 1);
> +  Print(L"FmpHeader:\n");
> +  Print(L"  Version             - 0x%x\n", FmpCapsuleHeader->Version);
> +  Print(L"  EmbeddedDriverCount - 0x%x\n", FmpCapsuleHeader->EmbeddedDriverCount);
> +  Print(L"  PayloadItemCount    - 0x%x\n", FmpCapsuleHeader->PayloadItemCount);
> +  Count = FmpCapsuleHeader->EmbeddedDriverCount + FmpCapsuleHeader->PayloadItemCount;
> +  for (Index = 0; Index < Count; Index++) {
> +    Print(L"  Offset[%d]           - 0x%x\n", Index, ItemOffsetList[Index]);
> +  }
> +
> +  for (Index = FmpCapsuleHeader->EmbeddedDriverCount; Index < Count; Index++) {
> +    Print(L"FmpPayload[%d] ImageHeader:\n", Index);
> +    FmpImageHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *)((UINT8
> *)FmpCapsuleHeader + ItemOffsetList[Index]);
> +    Print(L"  Version                - 0x%x\n", FmpImageHeader->Version);
> +    Print(L"  UpdateImageTypeId      - %g\n", &FmpImageHeader->UpdateImageTypeId);
> +    Print(L"  UpdateImageIndex       - 0x%x\n", FmpImageHeader->UpdateImageIndex);
> +    Print(L"  UpdateImageSize        - 0x%x\n", FmpImageHeader->UpdateImageSize);
> +    Print(L"  UpdateVendorCodeSize   - 0x%x\n", FmpImageHeader->UpdateVendorCodeSize);
> +    if (FmpImageHeader->Version >=
> EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {
> +      Print(L"  UpdateHardwareInstance - 0x%lx\n", FmpImageHeader-
> >UpdateHardwareInstance);
> +    }
> +  }
> +}
> +
> +/**
> +  Return if there is a FMP header below capsule header.
> +
> +  @param[in] CapsuleHeader A pointer to EFI_CAPSULE_HEADER
> +
> +  @retval TRUE  There is a FMP header below capsule header.
> +  @retval FALSE There is not a FMP header below capsule header
> +**/
> +BOOLEAN
> +IsNestedFmpCapsule(
> +  IN EFI_CAPSULE_HEADER         *CapsuleHeader
> +  )
> +{
> +  EFI_STATUS                 Status;
> +  EFI_SYSTEM_RESOURCE_TABLE  *Esrt;
> +  EFI_SYSTEM_RESOURCE_ENTRY  *EsrtEntry;
> +  UINTN                      Index;
> +  BOOLEAN                    EsrtGuidFound;
> +  EFI_CAPSULE_HEADER         *NestedCapsuleHeader;
> +  UINTN                      NestedCapsuleSize;
> +
> +  //
> +  // Check ESRT
> +  //
> +  EsrtGuidFound = FALSE;
> +  Status = EfiGetSystemConfigurationTable(&gEfiSystemResourceTableGuid, (VOID
> **)&Esrt);
> +  if (!EFI_ERROR(Status)) {
> +    EsrtEntry = (VOID *)(Esrt + 1);
> +    for (Index = 0; Index < Esrt->FwResourceCount; Index++, EsrtEntry++) {
> +      if (CompareGuid(&EsrtEntry->FwClass, &CapsuleHeader->CapsuleGuid)) {
> +        EsrtGuidFound = TRUE;
> +        break;
> +      }
> +    }
> +  }
> +
> +  if (!EsrtGuidFound) {
> +    return FALSE;
> +  }
> +
> +  //
> +  // Check nested capsule header
> +  // FMP GUID after ESRT one
> +  //
> +  NestedCapsuleHeader = (EFI_CAPSULE_HEADER *)((UINT8 *)CapsuleHeader + CapsuleHeader-
> >HeaderSize);
> +  NestedCapsuleSize = (UINTN)CapsuleHeader + CapsuleHeader->HeaderSize -
> (UINTN)NestedCapsuleHeader;
> +  if (NestedCapsuleSize < sizeof(EFI_CAPSULE_HEADER)) {
> +    return FALSE;
> +  }
> +  if (!CompareGuid(&NestedCapsuleHeader->CapsuleGuid, &gEfiFmpCapsuleGuid)) {
> +    return FALSE;
> +  }
> +  return TRUE;
> +}
> +
> +/**
> +  Dump capsule information
> +
> +  @retval EFI_SUCCESS            The capsule information is dumped.
> +  @retval EFI_UNSUPPORTED        Input parameter is not valid.
> +**/
> +EFI_STATUS
> +DumpCapsule(
> +  VOID
> +  )
> +{
> +  CHAR16                                        *CapsuleName;
> +  VOID                                          *Buffer;
> +  UINTN                                         FileSize;
> +  EFI_CAPSULE_HEADER                            *CapsuleHeader;
> +  EFI_STATUS                                    Status;
> +
> +  if (Argc != 3) {
> +    Print(L"CapsuleApp: Invalid Parameter.\n");
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  CapsuleName = Argv[2];
> +  Status = ReadFileToBuffer(CapsuleName, &FileSize, &Buffer);
> +  if (EFI_ERROR(Status)) {
> +    Print(L"CapsuleApp: Capsule (%s) is not found.\n", CapsuleName);
> +    goto Done;
> +  }
> +
> +  CapsuleHeader = Buffer;
> +  if (CompareGuid(&CapsuleHeader->CapsuleGuid, &gWindowsUxCapsuleGuid)) {
> +    DumpUxCapsule(CapsuleHeader);
> +    Status = EFI_SUCCESS;
> +    goto Done;
> +  }
> +
> +  if (CompareGuid(&CapsuleHeader->CapsuleGuid, &gEfiFmpCapsuleGuid)) {
> +    DumpFmpCapsule(CapsuleHeader);
> +  }
> +  if (IsNestedFmpCapsule(CapsuleHeader)) {
> +    Print(L"[NestedCapusule]\n");
> +    Print(L"CapsuleHeader:\n");
> +    Print(L"  CapsuleGuid      - %g\n", &CapsuleHeader->CapsuleGuid);
> +    Print(L"  HeaderSize       - 0x%x\n", CapsuleHeader->HeaderSize);
> +    Print(L"  Flags            - 0x%x\n", CapsuleHeader->Flags);
> +    Print(L"  CapsuleImageSize - 0x%x\n", CapsuleHeader->CapsuleImageSize);
> +    DumpFmpCapsule((EFI_CAPSULE_HEADER *)((UINTN)CapsuleHeader + CapsuleHeader-
> >HeaderSize));
> +  }
> +
> +Done:
> +  FreePool(Buffer);
> +  return Status;
> +}
> +
> +/**
> +  Dump capsule status variable.
> +
> +  @retval EFI_SUCCESS            The capsule status variable is dumped.
> +  @retval EFI_UNSUPPORTED        Input parameter is not valid.
> +**/
> +EFI_STATUS
> +DmpCapsuleStatusVariable(
> +  VOID
> +  )
> +{
> +  EFI_STATUS                          Status;
> +  UINT32                              Index;
> +  CHAR16                              CapsuleVarName[20];
> +  CHAR16                              *TempVarName;
> +  EFI_CAPSULE_RESULT_VARIABLE_HEADER  *CapsuleResult;
> +  EFI_CAPSULE_RESULT_VARIABLE_FMP     *CapsuleResultFmp;
> +  UINTN                               CapsuleFileNameSize;
> +  CHAR16                              CapsuleIndexData[12];
> +  CHAR16                              *CapsuleIndex;
> +
> +  Status = GetVariable2(
> +             L"CapsuleMax",
> +             &gEfiCapsuleReportGuid,
> +             (VOID **)&CapsuleIndex,
> +             NULL
> +             );
> +  if (!EFI_ERROR(Status)) {
> +    CopyMem(CapsuleIndexData, CapsuleIndex, 11 * sizeof(CHAR16));
> +    CapsuleIndexData[11] = 0;
> +    Print(L"CapsuleMax - %s\n", CapsuleIndexData);
> +    FreePool(CapsuleIndex);
> +  }
> +  Status = GetVariable2(
> +             L"CapsuleLast",
> +             &gEfiCapsuleReportGuid,
> +             (VOID **)&CapsuleIndex,
> +             NULL
> +             );
> +  if (!EFI_ERROR(Status)) {
> +    CopyMem(CapsuleIndexData, CapsuleIndex, 11 * sizeof(CHAR16));
> +    CapsuleIndexData[11] = 0;
> +    Print(L"CapsuleLast - %s\n", CapsuleIndexData);
> +    FreePool(CapsuleIndex);
> +  }
> +
> +
> +  StrCpyS (CapsuleVarName, sizeof(CapsuleVarName)/sizeof(CapsuleVarName[0]),
> L"Capsule");
> +  TempVarName = CapsuleVarName + StrLen (CapsuleVarName);
> +  Index = 0;
> +
> +  while (TRUE) {
> +    UnicodeSPrint (TempVarName, 5 * sizeof(CHAR16), L"%04x", Index);
> +
> +    Status = GetVariable2 (
> +               CapsuleVarName,
> +               &gEfiCapsuleReportGuid,
> +               (VOID **) &CapsuleResult,
> +               NULL
> +               );
> +    if (Status == EFI_NOT_FOUND) {
> +      break;
> +    } else if (EFI_ERROR(Status)) {
> +      continue;
> +    }
> +
> +    //
> +    // display capsule process status
> +    //
> +    if (CapsuleResult->VariableTotalSize >=
> sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER)) {
> +      Print (L"CapsuleName: %s\n", CapsuleVarName);
> +      Print (L"  Capsule Guid: %g\n", &CapsuleResult->CapsuleGuid);
> +      Print (L"  Capsule ProcessedTime: %t\n", &CapsuleResult->CapsuleProcessed);
> +      Print (L"  Capsule Status: %r\n", CapsuleResult->CapsuleStatus);
> +    }
> +
> +    if (CompareGuid(&CapsuleResult->CapsuleGuid, &gEfiFmpCapsuleGuid)) {
> +      if (CapsuleResult->VariableTotalSize >=
> sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER) + sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP)) {
> +        CapsuleResultFmp = (EFI_CAPSULE_RESULT_VARIABLE_FMP *)(CapsuleResult + 1);
> +        Print(L"  Capsule FMP Version: 0x%x\n", CapsuleResultFmp->Version);
> +        Print(L"  Capsule FMP PayloadIndex: 0x%x\n", CapsuleResultFmp->PayloadIndex);
> +        Print(L"  Capsule FMP UpdateImageIndex: 0x%x\n", CapsuleResultFmp-
> >UpdateImageIndex);
> +        Print(L"  Capsule FMP UpdateImageTypeId: %g\n", &CapsuleResultFmp-
> >UpdateImageTypeId);
> +        if (CapsuleResult->VariableTotalSize >
> sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER) + sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP)) {
> +          Print(L"  Capsule FMP CapsuleFileName: %s\n", (CapsuleResultFmp + 1));
> +          CapsuleFileNameSize = StrSize((CHAR16 *)(CapsuleResultFmp + 1));
> +          if (CapsuleResult->VariableTotalSize >
> sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER) + sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP) +
> CapsuleFileNameSize) {
> +            Print(L"  Capsule FMP CapsuleTarget: %s\n", (UINT8 *)(CapsuleResultFmp +
> 1) + CapsuleFileNameSize);
> +          }
> +        }
> +      }
> +    }
> +
> +    FreePool(CapsuleResult);
> +
> +    Index++;
> +    if (Index > 0xFFFF) {
> +      break;
> +    }
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +CHAR8 *mFwTypeString[] = {
> +  "Unknown",
> +  "SystemFirmware",
> +  "DeviceFirmware",
> +  "UefiDriver",
> +};
> +
> +CHAR8 *mLastAttemptStatusString[] = {
> +  "Success",
> +  "Error: Unsuccessful",
> +  "Error: Insufficient Resources",
> +  "Error: Incorrect Version",
> +  "Error: Invalid Format",
> +  "Error: Auth Error",
> +  "Error: Power Event AC",
> +  "Error: Power Event Battery",
> +};
> +
> +/**
> +  Convert FwType to a string.
> +
> +  @param FwType  FwType in ESRT
> +
> +  @return a string for FwType.
> +**/
> +CHAR8 *
> +FwTypeToString(
> +  IN UINT32 FwType
> +  )
> +{
> +  if (FwType < sizeof(mFwTypeString) / sizeof(mFwTypeString[0])) {
> +    return mFwTypeString[FwType];
> +  } else {
> +    return "Invalid";
> +  }
> +}
> +
> +/**
> +  Convert LastAttemptStatus to a string.
> +
> +  @param LastAttemptStatus  LastAttemptStatus in FMP or ESRT
> +
> +  @return a string for LastAttemptStatus.
> +**/
> +CHAR8 *
> +LastAttemptStatusToString(
> +  IN UINT32 LastAttemptStatus
> +  )
> +{
> +  if (LastAttemptStatus < sizeof(mLastAttemptStatusString) /
> sizeof(mLastAttemptStatusString[0])) {
> +    return mLastAttemptStatusString[LastAttemptStatus];
> +  } else {
> +    return "Error: Unknown";
> +  }
> +}
> +
> +/**
> +  Dump ESRT entry.
> +
> +  @param EsrtEntry  ESRT entry
> +**/
> +VOID
> +DumpEsrtEntry(
> +  IN EFI_SYSTEM_RESOURCE_ENTRY  *EsrtEntry
> +  )
> +{
> +  Print(L"  FwClass                  - %g\n", &EsrtEntry->FwClass);
> +  Print(L"  FwType                   - 0x%x (%a)\n", EsrtEntry->FwType,
> FwTypeToString(EsrtEntry->FwType));
> +  Print(L"  FwVersion                - 0x%x\n", EsrtEntry->FwVersion);
> +  Print(L"  LowestSupportedFwVersion - 0x%x\n", EsrtEntry->LowestSupportedFwVersion);
> +  Print(L"  CapsuleFlags             - 0x%x\n", EsrtEntry->CapsuleFlags);
> +  Print(L"    PERSIST_ACROSS_RESET   - 0x%x\n", EsrtEntry->CapsuleFlags &
> CAPSULE_FLAGS_PERSIST_ACROSS_RESET);
> +  Print(L"    POPULATE_SYSTEM_TABLE  - 0x%x\n", EsrtEntry->CapsuleFlags &
> CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE);
> +  Print(L"    INITIATE_RESET         - 0x%x\n", EsrtEntry->CapsuleFlags &
> CAPSULE_FLAGS_INITIATE_RESET);
> +  Print(L"  LastAttemptVersion       - 0x%x\n", EsrtEntry->LastAttemptVersion);
> +  Print(L"  LastAttemptStatus        - 0x%x (%a)\n", EsrtEntry->LastAttemptStatus,
> LastAttemptStatusToString(EsrtEntry->LastAttemptStatus));
> +}
> +
> +/**
> +  Dump ESRT table.
> +
> +  @param Esrt  ESRT table
> +**/
> +VOID
> +DumpEsrt(
> +  IN EFI_SYSTEM_RESOURCE_TABLE  *Esrt
> +  )
> +{
> +  UINTN                      Index;
> +  EFI_SYSTEM_RESOURCE_ENTRY  *EsrtEntry;
> +
> +  Print(L"EFI_SYSTEM_RESOURCE_TABLE:\n");
> +  Print(L"FwResourceCount    - 0x%x\n", Esrt->FwResourceCount);
> +  Print(L"FwResourceCountMax - 0x%x\n", Esrt->FwResourceCountMax);
> +  Print(L"FwResourceVersion  - 0x%lx\n", Esrt->FwResourceVersion);
> +
> +  EsrtEntry = (VOID *)(Esrt + 1);
> +  for (Index = 0; Index < Esrt->FwResourceCount; Index++) {
> +    Print(L"EFI_SYSTEM_RESOURCE_ENTRY (%d):\n", Index);
> +    DumpEsrtEntry(EsrtEntry);
> +    EsrtEntry++;
> +  }
> +}
> +
> +/**
> +  Dump ESRT info.
> +**/
> +VOID
> +DumpEsrtData (
> +  VOID
> +  )
> +{
> +  EFI_STATUS                 Status;
> +  EFI_SYSTEM_RESOURCE_TABLE  *Esrt;
> +
> +  Print(L"##############\n");
> +  Print(L"# ESRT TABLE #\n");
> +  Print(L"##############\n");
> +
> +  Status = EfiGetSystemConfigurationTable (&gEfiSystemResourceTableGuid, (VOID
> **)&Esrt);
> +  if (EFI_ERROR(Status)) {
> +    Print(L"ESRT - %r\n", Status);
> +    return;
> +  }
> +  DumpEsrt(Esrt);
> +  Print(L"\n");
> +}
> +
> +/**
> +  Dump FMP information.
> +
> +  @param ImageInfoSize       The size of ImageInfo, in bytes.
> +  @param ImageInfo           A pointer to EFI_FIRMWARE_IMAGE_DESCRIPTOR.
> +  @param DescriptorVersion   The version of EFI_FIRMWARE_IMAGE_DESCRIPTOR.
> +  @param DescriptorCount     The count of EFI_FIRMWARE_IMAGE_DESCRIPTOR.
> +  @param DescriptorSize      The size of an individual EFI_FIRMWARE_IMAGE_DESCRIPTOR,
> in bytes.
> +  @param PackageVersion      The version of package.
> +  @param PackageVersionName  The version name of package.
> +**/
> +VOID
> +DumpFmpImageInfo(
> +  IN UINTN                           ImageInfoSize,
> +  IN EFI_FIRMWARE_IMAGE_DESCRIPTOR   *ImageInfo,
> +  IN UINT32                          DescriptorVersion,
> +  IN UINT8                           DescriptorCount,
> +  IN UINTN                           DescriptorSize,
> +  IN UINT32                          PackageVersion,
> +  IN CHAR16                          *PackageVersionName
> +  )
> +{
> +  EFI_FIRMWARE_IMAGE_DESCRIPTOR                 *CurrentImageInfo;
> +  UINTN                                         Index;
> +
> +  Print(L"  DescriptorVersion  - 0x%x\n", DescriptorVersion);
> +  Print(L"  DescriptorCount    - 0x%x\n", DescriptorCount);
> +  Print(L"  DescriptorSize     - 0x%x\n", DescriptorSize);
> +  Print(L"  PackageVersion     - 0x%x\n", PackageVersion);
> +  Print(L"  PackageVersionName - \"%s\"\n", PackageVersionName);
> +  CurrentImageInfo = ImageInfo;
> +  for (Index = 0; Index < DescriptorCount; Index++) {
> +    Print(L"  ImageDescriptor (%d)\n", Index);
> +    Print(L"    ImageIndex                  - 0x%x\n", CurrentImageInfo->ImageIndex);
> +    Print(L"    ImageTypeId                 - %g\n", &CurrentImageInfo->ImageTypeId);
> +    Print(L"    ImageId                     - 0x%lx\n", CurrentImageInfo->ImageId);
> +    Print(L"    ImageIdName                 - \"%s\"\n", CurrentImageInfo-
> >ImageIdName);
> +    Print(L"    Version                     - 0x%x\n", CurrentImageInfo->Version);
> +    Print(L"    VersionName                 - \"%s\"\n", CurrentImageInfo-
> >VersionName);
> +    Print(L"    Size                        - 0x%x\n", CurrentImageInfo->Size);
> +    Print(L"    AttributesSupported         - 0x%lx\n", CurrentImageInfo-
> >AttributesSupported);
> +    Print(L"      IMAGE_UPDATABLE           - 0x%lx\n", CurrentImageInfo-
> >AttributesSupported & IMAGE_ATTRIBUTE_IMAGE_UPDATABLE);
> +    Print(L"      RESET_REQUIRED            - 0x%lx\n", CurrentImageInfo-
> >AttributesSupported & IMAGE_ATTRIBUTE_RESET_REQUIRED);
> +    Print(L"      AUTHENTICATION_REQUIRED   - 0x%lx\n", CurrentImageInfo-
> >AttributesSupported & IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);
> +    Print(L"      IN_USE                    - 0x%lx\n", CurrentImageInfo-
> >AttributesSupported & IMAGE_ATTRIBUTE_IN_USE);
> +    Print(L"      UEFI_IMAGE                - 0x%lx\n", CurrentImageInfo-
> >AttributesSupported & IMAGE_ATTRIBUTE_UEFI_IMAGE);
> +    Print(L"    AttributesSetting           - 0x%lx\n", CurrentImageInfo-
> >AttributesSetting);
> +    Print(L"      IMAGE_UPDATABLE           - 0x%lx\n", CurrentImageInfo-
> >AttributesSetting & IMAGE_ATTRIBUTE_IMAGE_UPDATABLE);
> +    Print(L"      RESET_REQUIRED            - 0x%lx\n", CurrentImageInfo-
> >AttributesSetting & IMAGE_ATTRIBUTE_RESET_REQUIRED);
> +    Print(L"      AUTHENTICATION_REQUIRED   - 0x%lx\n", CurrentImageInfo-
> >AttributesSetting & IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);
> +    Print(L"      IN_USE                    - 0x%lx\n", CurrentImageInfo-
> >AttributesSetting & IMAGE_ATTRIBUTE_IN_USE);
> +    Print(L"      UEFI_IMAGE                - 0x%lx\n", CurrentImageInfo-
> >AttributesSetting & IMAGE_ATTRIBUTE_UEFI_IMAGE);
> +    Print(L"    Compatibilities             - 0x%lx\n", CurrentImageInfo-
> >Compatibilities);
> +    Print(L"      COMPATIB_CHECK_SUPPORTED  - 0x%lx\n", CurrentImageInfo-
> >Compatibilities & IMAGE_COMPATIBILITY_CHECK_SUPPORTED);
> +    if (DescriptorVersion > 1) {
> +      Print(L"    LowestSupportedImageVersion - 0x%x\n", CurrentImageInfo-
> >LowestSupportedImageVersion);
> +      if (DescriptorVersion > 2) {
> +        Print(L"    LastAttemptVersion          - 0x%x\n", CurrentImageInfo-
> >LastAttemptVersion);
> +        Print(L"    LastAttemptStatus           - 0x%x (%a)\n", CurrentImageInfo-
> >LastAttemptStatus, LastAttemptStatusToString(CurrentImageInfo->LastAttemptStatus));
> +        Print(L"    HardwareInstance            - 0x%lx\n", CurrentImageInfo-
> >HardwareInstance);
> +      }
> +    }
> +    //
> +    // Use DescriptorSize to move ImageInfo Pointer to stay compatible with different
> ImageInfo version
> +    //
> +    CurrentImageInfo = (EFI_FIRMWARE_IMAGE_DESCRIPTOR *)((UINT8 *)CurrentImageInfo +
> DescriptorSize);
> +  }
> +}
> +
> +/**
> +  Dump FMP package information.
> +
> +  @param PackageVersion             The version of package.
> +  @param PackageVersionName         The version name of package.
> +  @param PackageVersionNameMaxLen   The maximum length of PackageVersionName.
> +  @param AttributesSupported        Package attributes that are supported by this
> device.
> +  @param AttributesSetting          Package attributes.
> +**/
> +VOID
> +DumpFmpPackageInfo(
> +  IN UINT32                           PackageVersion,
> +  IN CHAR16                           *PackageVersionName,
> +  IN UINT32                           PackageVersionNameMaxLen,
> +  IN UINT64                           AttributesSupported,
> +  IN UINT64                           AttributesSetting
> +  )
> +{
> +  Print(L"  PackageVersion              - 0x%x\n", PackageVersion);
> +  Print(L"  PackageVersionName          - \"%s\"\n", PackageVersionName);
> +  Print(L"  PackageVersionNameMaxLen    - 0x%x\n", PackageVersionNameMaxLen);
> +  Print(L"  AttributesSupported         - 0x%lx\n", AttributesSupported);
> +  Print(L"    IMAGE_UPDATABLE           - 0x%lx\n", AttributesSupported &
> IMAGE_ATTRIBUTE_IMAGE_UPDATABLE);
> +  Print(L"    RESET_REQUIRED            - 0x%lx\n", AttributesSupported &
> IMAGE_ATTRIBUTE_RESET_REQUIRED);
> +  Print(L"    AUTHENTICATION_REQUIRED   - 0x%lx\n", AttributesSupported &
> IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);
> +  Print(L"  AttributesSetting           - 0x%lx\n", AttributesSetting);
> +  Print(L"    IMAGE_UPDATABLE           - 0x%lx\n", AttributesSetting &
> IMAGE_ATTRIBUTE_IMAGE_UPDATABLE);
> +  Print(L"    RESET_REQUIRED            - 0x%lx\n", AttributesSetting &
> IMAGE_ATTRIBUTE_RESET_REQUIRED);
> +  Print(L"    AUTHENTICATION_REQUIRED   - 0x%lx\n", AttributesSetting &
> IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);
> +}
> +
> +/**
> +  Dump FMP protocol info.
> +**/
> +VOID
> +DumpFmpData (
> +  VOID
> +  )
> +{
> +  EFI_STATUS                                    Status;
> +  EFI_FIRMWARE_MANAGEMENT_PROTOCOL              *Fmp;
> +  EFI_HANDLE                                    *HandleBuffer;
> +  UINTN                                         NumberOfHandles;
> +  UINTN                                         Index;
> +  EFI_FIRMWARE_IMAGE_DESCRIPTOR                 *FmpImageInfoBuf;
> +  UINTN                                         ImageInfoSize;
> +  UINT32                                        FmpImageInfoDescriptorVer;
> +  UINT8                                         FmpImageInfoCount;
> +  UINTN                                         DescriptorSize;
> +  UINT32                                        PackageVersion;
> +  CHAR16                                        *PackageVersionName;
> +  UINT32                                        PackageVersionNameMaxLen;
> +  UINT64                                        AttributesSupported;
> +  UINT64                                        AttributesSetting;
> +
> +  Print(L"############\n");
> +  Print(L"# FMP DATA #\n");
> +  Print(L"############\n");
> +  Status = gBS->LocateHandleBuffer (
> +                  ByProtocol,
> +                  &gEfiFirmwareManagementProtocolGuid,
> +                  NULL,
> +                  &NumberOfHandles,
> +                  &HandleBuffer
> +                  );
> +  if (EFI_ERROR(Status)) {
> +    Print(L"FMP protocol - %r\n", EFI_NOT_FOUND);
> +    return;
> +  }
> +
> +  for (Index = 0; Index < NumberOfHandles; Index++) {
> +    Status = gBS->HandleProtocol(
> +                    HandleBuffer[Index],
> +                    &gEfiFirmwareManagementProtocolGuid,
> +                    (VOID **)&Fmp
> +                    );
> +    if (EFI_ERROR(Status)) {
> +      continue;
> +    }
> +
> +    ImageInfoSize = 0;
> +    Status = Fmp->GetImageInfo (
> +                    Fmp,
> +                    &ImageInfoSize,
> +                    NULL,
> +                    NULL,
> +                    NULL,
> +                    NULL,
> +                    NULL,
> +                    NULL
> +                    );
> +    if (Status != EFI_BUFFER_TOO_SMALL) {
> +      continue;
> +    }
> +
> +    FmpImageInfoBuf = NULL;
> +    FmpImageInfoBuf = AllocateZeroPool (ImageInfoSize);
> +    if (FmpImageInfoBuf == NULL) {
> +      Status = EFI_OUT_OF_RESOURCES;
> +      goto EXIT;
> +    }
> +
> +    PackageVersionName = NULL;
> +    Status = Fmp->GetImageInfo (
> +                    Fmp,
> +                    &ImageInfoSize,               // ImageInfoSize
> +                    FmpImageInfoBuf,              // ImageInfo
> +                    &FmpImageInfoDescriptorVer,   // DescriptorVersion
> +                    &FmpImageInfoCount,           // DescriptorCount
> +                    &DescriptorSize,              // DescriptorSize
> +                    &PackageVersion,              // PackageVersion
> +                    &PackageVersionName           // PackageVersionName
> +                    );
> +
> +    //
> +    // If FMP GetInformation interface failed, skip this resource
> +    //
> +    if (EFI_ERROR(Status)) {
> +      Print(L"FMP (%d) ImageInfo - %r\n", Index, Status);
> +      FreePool(FmpImageInfoBuf);
> +      continue;
> +    }
> +
> +    Print(L"FMP (%d) ImageInfo:\n", Index);
> +    DumpFmpImageInfo(
> +      ImageInfoSize,               // ImageInfoSize
> +      FmpImageInfoBuf,             // ImageInfo
> +      FmpImageInfoDescriptorVer,   // DescriptorVersion
> +      FmpImageInfoCount,           // DescriptorCount
> +      DescriptorSize,              // DescriptorSize
> +      PackageVersion,              // PackageVersion
> +      PackageVersionName           // PackageVersionName
> +      );
> +
> +    if (PackageVersionName != NULL) {
> +      FreePool(PackageVersionName);
> +    }
> +    FreePool(FmpImageInfoBuf);
> +
> +    //
> +    // Get package info
> +    //
> +    PackageVersionName = NULL;
> +    Status = Fmp->GetPackageInfo (
> +                    Fmp,
> +                    &PackageVersion,              // PackageVersion
> +                    &PackageVersionName,          // PackageVersionName
> +                    &PackageVersionNameMaxLen,    // PackageVersionNameMaxLen
> +                    &AttributesSupported,         // AttributesSupported
> +                    &AttributesSetting            // AttributesSetting
> +                    );
> +    if (EFI_ERROR(Status)) {
> +      Print(L"FMP (%d) PackageInfo - %r\n", Index, Status);
> +    } else {
> +      Print(L"FMP (%d) ImageInfo:\n", Index);
> +      DumpFmpPackageInfo(
> +        PackageVersion,              // PackageVersion
> +        PackageVersionName,          // PackageVersionName
> +        PackageVersionNameMaxLen,    // PackageVersionNameMaxLen
> +        AttributesSupported,         // AttributesSupported
> +        AttributesSetting            // AttributesSetting
> +        );
> +
> +      if (PackageVersionName != NULL) {
> +        FreePool(PackageVersionName);
> +      }
> +    }
> +  }
> +  Print(L"\n");
> +
> +EXIT:
> +  FreePool(HandleBuffer);
> +}
> --
> 2.7.4.windows.1



  parent reply	other threads:[~2016-10-27  0:13 UTC|newest]

Thread overview: 32+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-10-23  2:20 [PATCH V4 00/15] Add capsule support lib and app Jiewen Yao
2016-10-23  2:20 ` [PATCH V4 01/15] MdeModulePkg/Include: Add FmpAuthenticationLib header Jiewen Yao
2016-10-25 23:54   ` Kinney, Michael D
2016-10-26  0:50     ` Yao, Jiewen
2016-10-26  2:06       ` Kinney, Michael D
2016-10-23  2:20 ` [PATCH V4 02/15] MdeModulePkg/CapsuleLib: Add ProcessCapsules() API Jiewen Yao
2016-10-23  2:20 ` [PATCH V4 03/15] MdeModulePkg/MdeModulePkg.dec: Add capsule related definition Jiewen Yao
2016-10-26  2:01   ` Kinney, Michael D
2016-10-26  2:27     ` Yao, Jiewen
2016-10-26  3:00       ` Kinney, Michael D
2016-10-26  4:45         ` Yao, Jiewen
2016-10-26  4:58           ` Yao, Jiewen
2016-10-23  2:20 ` [PATCH V4 04/15] MdeModulePkg/FmpAuthenticationLibNull: Add NULL instance FMP Jiewen Yao
2016-10-23  2:20 ` [PATCH V4 05/15] MdeModulePkg/DxeCapsuleLibNull: Add ProcessCapsules() interface Jiewen Yao
2016-10-23  2:20 ` [PATCH V4 06/15] MdeModulePkg/DxeCapsuleLibFmp: Add DxeCapsuleLibFmp instance Jiewen Yao
2016-10-27  0:09   ` Kinney, Michael D
2016-10-27  1:33     ` Yao, Jiewen
2016-10-23  2:20 ` [PATCH V4 07/15] MdeModulePkg/Esrt: Add ESRT_FW_TYPE_SYSTEMFIRMWARE check Jiewen Yao
2016-10-23  2:20 ` [PATCH V4 08/15] MdeModulePkg/CapsuleApp: Add CapsuleApp application Jiewen Yao
2016-10-25 23:26   ` Kinney, Michael D
2016-10-26  0:42     ` Yao, Jiewen
2016-10-26  1:50       ` Yao, Jiewen
2016-10-26  2:05       ` Kinney, Michael D
2016-10-26  2:19         ` Yao, Jiewen
2016-10-27  0:13   ` Kinney, Michael D [this message]
2016-10-23  2:20 ` [PATCH V4 09/15] MdeModulePkg/UiApp: Show test key warning info in FrontPage Jiewen Yao
2016-10-23  2:20 ` [PATCH V4 10/15] MdeModulePkg/MdeModulePkg.dsc: Add FMP related component Jiewen Yao
2016-10-23  2:20 ` [PATCH V4 11/15] IntelFrameworkModulePkg/DxeCapsuleLib: Add ProcessCapsules() interface Jiewen Yao
2016-10-23  2:20 ` [PATCH V4 12/15] SecurityPkg/SecurityPkg.dec: Add PcdPkcs7CertBuffer PCD Jiewen Yao
2016-10-23  2:20 ` [PATCH V4 13/15] SecurityPkg/FmpAuthenticationLibPkcs7: Add PKCS7 instance for FMP Jiewen Yao
2016-10-23  2:20 ` [PATCH V4 14/15] SecurityPkg/FmpAuthenticationLibRsa2048Sha256: Add RSA2048 instance Jiewen Yao
2016-10-23  2:20 ` [PATCH V4 15/15] SecurityPkg/SecurityPkg.dsc: Add FmpAuthenticationLib* Jiewen Yao

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=E92EE9817A31E24EB0585FDF735412F56483B94F@ORSMSX113.amr.corp.intel.com \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox