This MicrocodeCapsuleApp can help generate Microcode FMP capsule.
It can also dump Microcode capsule information.

Cc: Jeff Fan <jeff....@intel.com>
Cc: Feng Tian <feng.t...@intel.com>
Cc: Star Zeng <star.z...@intel.com>
Cc: Michael D Kinney <michael.d.kin...@intel.com>
Cc: Liming Gao <liming....@intel.com>
Cc: Chao Zhang <chao.b.zh...@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiewen Yao <jiewen....@intel.com>
Reviewed-by: Jeff Fan <jeff....@intel.com>
---
 UefiCpuPkg/Application/MicrocodeCapsuleApp/AppSupport.c                 | 443 
++++++++++++++++++++
 UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.c        | 268 
++++++++++++
 UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.inf      |  63 
+++
 UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.uni      |  22 +
 UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleAppExtra.uni |  19 +
 UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleDump.c       | 171 
++++++++
 6 files changed, 986 insertions(+)

diff --git a/UefiCpuPkg/Application/MicrocodeCapsuleApp/AppSupport.c 
b/UefiCpuPkg/Application/MicrocodeCapsuleApp/AppSupport.c
new file mode 100644
index 0000000..0ab016c
--- /dev/null
+++ b/UefiCpuPkg/Application/MicrocodeCapsuleApp/AppSupport.c
@@ -0,0 +1,443 @@
+/** @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>
+
+UINTN  Argc = 0;
+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[in]  Vol             File System Volume
+  @param[in]  FileName        The file to be read.
+  @param[out] BufferSize      The file buffer size
+  @param[out] 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[in]  ThisVol         File System Volume
+  @param[in]  FileName        The file to be read.
+  @param[out] BufferSize      The file buffer size
+  @param[out] Buffer          The file buffer
+  @param[in]  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[in]  FileName        The file to be read.
+  @param[out] BufferSize      The file buffer size
+  @param[out] 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[in] FileName        The file to be written.
+  @param[in] BufferSize      The file buffer size
+  @param[in] 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/UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.c 
b/UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.c
new file mode 100644
index 0000000..aaa4399
--- /dev/null
+++ b/UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.c
@@ -0,0 +1,268 @@
+/** @file
+  A shell application that generates Microcode FMP 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 <Guid/FileInfo.h>
+#include <Guid/FmpCapsule.h>
+#include <Guid/MicrocodeFmp.h>
+
+#define CAPSULE_HEADER_SIZE  0x20
+
+#define MAJOR_VERSION   1
+#define MINOR_VERSION   0
+
+#define MAX_CAPSULE_NUM 10
+
+extern UINTN  Argc;
+extern CHAR16 **Argv;
+
+/**
+  Dump capsule information
+
+  @retval EFI_SUCCESS            The capsule information is dumped.
+  @retval EFI_UNSUPPORTED        Input parameter is not valid.
+**/
+EFI_STATUS
+DumpCapsule (
+  VOID
+  );
+
+/**
+  Read a file.
+
+  @param[in] FileName        The file to be read.
+  @param[in] BufferSize      The file buffer size
+  @param[in] 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[in] FileName        The file to be written.
+  @param[in] BufferSize      The file buffer size
+  @param[in] 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 Microcode FMP 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 Microcode 
capsule.
+**/
+EFI_STATUS
+CreateMicrocodeFmp (
+  VOID
+  )
+{
+  CHAR16                                        *OutputCapsuleName;
+  VOID                                          
*MicrocodeBuffer[MAX_CAPSULE_NUM];
+  UINTN                                         FileSize[MAX_CAPSULE_NUM];
+  CHAR16                                        *MicrocodeName;
+  UINTN                                         MicrocodeNum;
+  UINTN                                         MicrocodeFirstIndex;
+  UINTN                                         MicrocodeLastIndex;
+  UINTN                                         Index;
+  UINT8                                         *FullFmpBuffer;
+  UINTN                                         FullFmpBufferSize;
+  EFI_CAPSULE_HEADER                            *CapsuleHeader;
+  EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER        *FmpHeader;
+  EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER  *FmpImageHeader;
+  UINT64                                        *ItemOffsetList;
+  EFI_STATUS                                    Status;
+
+  if (StrCmp(Argv[Argc - 2], L"-O") != 0) {
+    Print(L"CapsuleApp: NO output capsule name.\n");
+    return EFI_UNSUPPORTED;
+  }
+  OutputCapsuleName = Argv[Argc - 1];
+
+  MicrocodeFirstIndex = 2;
+  MicrocodeLastIndex = Argc - 3;
+  MicrocodeNum = MicrocodeLastIndex - MicrocodeFirstIndex + 1;
+
+  if (MicrocodeFirstIndex > MicrocodeLastIndex) {
+    Print(L"CapsuleApp: NO Microcode image.\n");
+    return EFI_UNSUPPORTED;
+  }
+  if (MicrocodeNum > MAX_CAPSULE_NUM) {
+    Print(L"CapsuleApp: Too many Microcode images.\n");
+    return EFI_UNSUPPORTED;
+  }
+
+  ZeroMem(&MicrocodeBuffer, sizeof(MicrocodeBuffer));
+  ZeroMem(&FileSize, sizeof(FileSize));
+  FullFmpBuffer = NULL;
+
+  FullFmpBufferSize = CAPSULE_HEADER_SIZE + 
sizeof(EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER) + sizeof(UINT64) * MicrocodeNum;
+  for (Index = 0; Index < MicrocodeNum; Index++) {
+    MicrocodeName = Argv[MicrocodeFirstIndex + Index];
+    Status = ReadFileToBuffer(MicrocodeName, &FileSize[Index], 
&MicrocodeBuffer[Index]);
+    if (EFI_ERROR(Status)) {
+      Print(L"CapsuleApp: Microcode image (%s) is not found.\n", 
MicrocodeName);
+      goto Done;
+    }
+    FullFmpBufferSize += sizeof(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER) 
+ FileSize[Index];
+  }
+
+  FullFmpBuffer = AllocatePool(FullFmpBufferSize);
+  if (FullFmpBuffer == NULL) {
+    Print(L"CapsuleApp: Fmp Buffer size (0x%x) too big.\n", FullFmpBufferSize);
+    Status = EFI_OUT_OF_RESOURCES;
+    goto Done;
+  }
+
+  CapsuleHeader = (EFI_CAPSULE_HEADER *)FullFmpBuffer;
+  CopyGuid(&CapsuleHeader->CapsuleGuid, &gEfiFmpCapsuleGuid);
+  CapsuleHeader->HeaderSize = CAPSULE_HEADER_SIZE;
+  CapsuleHeader->Flags = CAPSULE_FLAGS_PERSIST_ACROSS_RESET | 
CAPSULE_FLAGS_INITIATE_RESET;
+  CapsuleHeader->CapsuleImageSize = (UINT32)FullFmpBufferSize;
+  ZeroMem(CapsuleHeader + 1, CAPSULE_HEADER_SIZE - sizeof(EFI_CAPSULE_HEADER));
+
+  FmpHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *)((UINT8 
*)CapsuleHeader + CapsuleHeader->HeaderSize);
+  FmpHeader->Version = EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION;
+  FmpHeader->EmbeddedDriverCount = 0;
+  FmpHeader->PayloadItemCount = (UINT16)MicrocodeNum;
+  ItemOffsetList = (UINT64 *)(FmpHeader + 1);
+  ItemOffsetList[0] = (UINTN)&ItemOffsetList[FmpHeader->EmbeddedDriverCount + 
FmpHeader->PayloadItemCount] - (UINTN)FmpHeader;
+  for (Index = 1; Index < MicrocodeNum; Index++) {
+    ItemOffsetList[Index] = ItemOffsetList[Index - 1] + 
sizeof(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER) + FileSize[Index - 1];
+  }
+
+  FmpImageHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER 
*)(&ItemOffsetList[FmpHeader->EmbeddedDriverCount + 
FmpHeader->PayloadItemCount]);
+  for (Index = 0; Index < MicrocodeNum; Index++) {
+    FmpImageHeader->Version = 
EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION;
+    CopyGuid (&FmpImageHeader->UpdateImageTypeId, 
&gMicrocodeFmpImageTypeIdGuid);
+    FmpImageHeader->UpdateImageIndex = (UINT8)(Index + 1);
+    ZeroMem(FmpImageHeader->reserved_bytes, 
sizeof(FmpImageHeader->reserved_bytes));
+    FmpImageHeader->UpdateImageSize = (UINT32)FileSize[Index];
+    FmpImageHeader->UpdateVendorCodeSize = 0;
+    FmpImageHeader->UpdateHardwareInstance = 0;
+    CopyMem(FmpImageHeader + 1, MicrocodeBuffer[Index], FileSize[Index]);
+
+    FmpImageHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *)((UINT8 
*)FmpImageHeader + sizeof(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER) + 
FmpImageHeader->UpdateImageSize + FmpImageHeader->UpdateVendorCodeSize);
+  }
+
+  Status = WriteFileFromBuffer(OutputCapsuleName, FullFmpBufferSize, 
FullFmpBuffer);
+  Print(L"CapsuleApp: Write %s %r\n", OutputCapsuleName, Status);
+
+Done:
+  for (Index = 0; Index < MicrocodeNum; Index++) {
+    if (MicrocodeBuffer[Index] != NULL) {
+      FreePool(MicrocodeBuffer[Index]);
+    }
+  }
+
+  if (FullFmpBuffer != NULL) {
+    FreePool(FullFmpBuffer);
+  }
+
+  return Status;
+}
+
+/**
+  Print APP usage.
+**/
+VOID
+PrintUsage (
+  VOID
+  )
+{
+  Print(L"MicrocodeCapsuleApp:  usage\n");
+  Print(L"  MicrocodeCapsuleApp -U <Microcode...> -O <Capsule>\n");
+  Print(L"  MicrocodeCapsuleApp -D <Capsule>\n");
+  Print(L"Parameter:\n");
+  Print(L"  -U:  Input Microcode binary 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;
+
+  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"-U") == 0) {
+    Status = CreateMicrocodeFmp();
+    return Status;
+  }
+
+  Status = EFI_UNSUPPORTED;
+
+  return Status;
+}
diff --git a/UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.inf 
b/UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.inf
new file mode 100644
index 0000000..d6a5c85
--- /dev/null
+++ b/UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.inf
@@ -0,0 +1,63 @@
+##  @file
+#  A shell application that generates Microcode FMP capsule.
+#
+# This application can generates Microcode FMP capsule. It can also
+# dump Microcode FMP capsule 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                      = MicrocodeCapsuleApp
+  MODULE_UNI_FILE                = MicrocodeCapsuleApp.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]
+  MicrocodeCapsuleApp.c
+  MicrocodeCapsuleDump.c
+  AppSupport.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  UefiCpuPkg/UefiCpuPkg.dec
+
+[Guids]
+  gEfiFileInfoGuid
+  gEfiFmpCapsuleGuid
+  gMicrocodeFmpImageTypeIdGuid
+
+[Protocols]
+  gEfiLoadedImageProtocolGuid
+  gEfiSimpleFileSystemProtocolGuid
+  gEfiShellParametersProtocolGuid
+
+[LibraryClasses]
+  BaseLib
+  UefiApplicationEntryPoint
+  DebugLib
+  MemoryAllocationLib
+  UefiBootServicesTableLib
+  UefiRuntimeServicesTableLib
+  UefiLib
+  PrintLib
+
+[UserExtensions.TianoCore."ExtraFiles"]
+  MicrocodeCapsuleAppExtra.uni
diff --git a/UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.uni 
b/UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.uni
new file mode 100644
index 0000000..1d13057
--- /dev/null
+++ b/UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.uni
@@ -0,0 +1,22 @@
+// /** @file
+// A shell application that generates Microcode FMP capsule.
+//
+// This application can generates Microcode FMP capsule. It can also
+// dump Microcode FMP capsule 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 generates Microcode FMP capsule."
+
+#string STR_MODULE_DESCRIPTION          #language en-US "This application can 
generates Microcode FMP capsule. It can also dump Microcode FMP capsule 
information."
+
diff --git 
a/UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleAppExtra.uni 
b/UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleAppExtra.uni
new file mode 100644
index 0000000..3ba1610
--- /dev/null
+++ b/UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleAppExtra.uni
@@ -0,0 +1,19 @@
+// /** @file
+// MicrocodeCapsuleApp 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
+"MicrocodeCapsule Application"
+
+
diff --git a/UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleDump.c 
b/UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleDump.c
new file mode 100644
index 0000000..48a1579
--- /dev/null
+++ b/UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleDump.c
@@ -0,0 +1,171 @@
+/** @file
+  Dump Microcode 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 <Guid/FmpCapsule.h>
+#include <Guid/MicrocodeFmp.h>
+#include <Register/Microcode.h>
+
+/**
+  Read a file.
+
+  @param[in]  FileName        The file to be read.
+  @param[out] BufferSize      The file buffer size
+  @param[out] 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 Microcode FMP capsule.
+
+  @param[in] Image      The Microcode FMP capsule.
+  @param[in] ImageSize  The size of the Microcode FMP capsule in bytes.
+**/
+VOID
+DumpMicrocodeFmpCapsule (
+  IN VOID   *Image,
+  IN UINTN  ImageSize
+  )
+{
+  CPU_MICROCODE_HEADER  *MicrocodeHeader;
+
+  MicrocodeHeader = Image;
+  Print(L"[Microcode]\n");
+  Print(L"  HeaderVersion   - 0x%08x\n", MicrocodeHeader->HeaderVersion);
+  Print(L"  UpdateRevision  - 0x%08x\n", MicrocodeHeader->UpdateRevision);
+  Print(L"  Date            - 0x%08x\n", MicrocodeHeader->Date.Uint32);
+  Print(L"  ProcessorId     - 0x%08x\n", 
MicrocodeHeader->ProcessorSignature.Uint32);
+  Print(L"  Checksum        - 0x%08x\n", MicrocodeHeader->Checksum);
+  Print(L"  LoaderRevision  - 0x%08x\n", MicrocodeHeader->LoaderRevision);
+  Print(L"  ProcessorFlags  - 0x%08x\n", MicrocodeHeader->ProcessorFlags);
+  Print(L"  DataSize        - 0x%08x\n", MicrocodeHeader->DataSize);
+  Print(L"  TotalSize       - 0x%08x\n", MicrocodeHeader->TotalSize);
+}
+
+/**
+  Dump a Microcode FMP capsule.
+
+  @param[in]  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;
+  VOID                                          *Image;
+
+  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);
+    }
+    if (FmpImageHeader->Version >= 
EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {
+      Image = (UINT8 *)(FmpImageHeader + 1);
+    }  else {
+      Image = (UINT8 *)FmpImageHeader + 
OFFSET_OF(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER, UpdateHardwareInstance);
+    }
+    if (CompareGuid (&FmpImageHeader->UpdateImageTypeId, 
&gMicrocodeFmpImageTypeIdGuid)) {
+      DumpMicrocodeFmpCapsule(Image, FmpImageHeader->UpdateImageSize);
+    }
+  }
+}
+
+/**
+  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, &gEfiFmpCapsuleGuid)) {
+    DumpFmpCapsule(CapsuleHeader);
+  }
+
+Done:
+  FreePool(Buffer);
+  return Status;
+}
+
-- 
2.7.4.windows.1

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel

Reply via email to