From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga09.intel.com (mga09.intel.com [134.134.136.24]) (using TLSv1 with cipher CAMELLIA256-SHA (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id 7BD0D1A1E73 for ; Tue, 20 Sep 2016 23:47:10 -0700 (PDT) Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by orsmga102.jf.intel.com with ESMTP; 20 Sep 2016 23:47:10 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.30,372,1470726000"; d="scan'208";a="1059859242" Received: from jyao1-mobl.ccr.corp.intel.com ([10.239.192.109]) by fmsmga002.fm.intel.com with ESMTP; 20 Sep 2016 23:47:08 -0700 From: Jiewen Yao To: edk2-devel@lists.01.org Cc: Jeff Fan , Feng Tian , Star Zeng , Michael D Kinney , Liming Gao , Chao Zhang Date: Wed, 21 Sep 2016 14:45:10 +0800 Message-Id: <1474440326-9292-30-git-send-email-jiewen.yao@intel.com> X-Mailer: git-send-email 2.7.4.windows.1 In-Reply-To: <1474440326-9292-1-git-send-email-jiewen.yao@intel.com> References: <1474440326-9292-1-git-send-email-jiewen.yao@intel.com> Subject: [PATCH 29/45] UefiCpuPkg/MicrocodeCapsuleApp: Add MicrocodeCapsuleApp application. X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 21 Sep 2016 06:47:10 -0000 This MicrocodeCapsuleApp can help generate Microcode FMP capsule. It can also dump Microcode capsule information. Cc: Jeff Fan Cc: Feng Tian Cc: Star Zeng Cc: Michael D Kinney Cc: Liming Gao Cc: Chao Zhang Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Jiewen Yao --- UefiCpuPkg/Application/MicrocodeCapsuleApp/AppSupport.c | 480 ++++++++++++++++++++ UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.c | 283 ++++++++++++ UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.inf | 62 +++ UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.uni | 22 + UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleAppExtra.uni | 19 + UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleDump.c | 171 +++++++ 6 files changed, 1037 insertions(+) diff --git a/UefiCpuPkg/Application/MicrocodeCapsuleApp/AppSupport.c b/UefiCpuPkg/Application/MicrocodeCapsuleApp/AppSupport.c new file mode 100644 index 0000000..365067d --- /dev/null +++ b/UefiCpuPkg/Application/MicrocodeCapsuleApp/AppSupport.c @@ -0,0 +1,480 @@ +/** @file + A shell application that triggers capsule update process. + + Copyright (c) 2016, Intel Corporation. All rights reserved.
+ 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_ARG_NUM 11 + +UINTN Argc = 0; +CHAR16 *Argv[MAX_ARG_NUM]; +CHAR16 *ArgBuffer; + +/** + + This function parse application ARG. + + @return Status +**/ +EFI_STATUS +GetArg ( + VOID + ) +{ + UINT8 *Data; + UINTN DataSize; + CHAR16 *Index; + CHAR16 *End; + CHAR16 *DIndex; + EFI_STATUS Status; + EFI_LOADED_IMAGE_PROTOCOL *LoadedImage; + + Status = gBS->HandleProtocol ( + gImageHandle, + &gEfiLoadedImageProtocolGuid, + (VOID**)&LoadedImage + ); + if (EFI_ERROR(Status)) { + return Status; + } + + Data = LoadedImage->LoadOptions; + DataSize = LoadedImage->LoadOptionsSize; + + End = (CHAR16*)(UINTN)(Data + DataSize); + Status = gBS->AllocatePool (EfiBootServicesData, DataSize, (VOID **)&ArgBuffer); + ASSERT_EFI_ERROR (Status); + DIndex = ArgBuffer; + Argv[Argc++] = ArgBuffer; + for (Index = (CHAR16*)Data; Index < End; ) { + if (*Index == L' ') { + *DIndex = L'\0'; + if (Argc >= MAX_ARG_NUM) { + return EFI_UNSUPPORTED; + } + Argv[Argc++] = (++ DIndex); + while(*Index == L' ') { + Index ++; + } + } + (*(DIndex ++)) = (*(Index ++)); + } + return EFI_SUCCESS; +} + +/** + Clear APP ARG. +**/ +VOID +CleanArg ( + VOID + ) +{ + FreePool (Argv[0]); +} + +/** + 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/UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.c b/UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.c new file mode 100644 index 0000000..bb79b98 --- /dev/null +++ b/UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.c @@ -0,0 +1,283 @@ +/** @file + A shell application that generates Microcode FMP capsule update process. + + Copyright (c) 2016, Intel Corporation. All rights reserved.
+ 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define CAPSULE_HEADER_SIZE 0x20 + +#define MAJOR_VERSION 1 +#define MINOR_VERSION 0 + +#define MAX_ARG_NUM 11 +#define MAX_CAPSULE_NUM (MAX_ARG_NUM - 1) + +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 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 + ); + +/** + Clear APP ARG. +**/ +VOID +CleanArg ( + 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"); + CleanArg(); + return EFI_UNSUPPORTED; + } + if (MicrocodeNum > MAX_CAPSULE_NUM) { + Print(L"CapsuleApp: Too many Microcode images.\n"); + CleanArg(); + 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 -O \n"); + Print(L" MicrocodeCapsuleApp -D \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)) { + PrintUsage(); + return Status; + } + if (Argc < 2) { + PrintUsage(); + CleanArg(); + return EFI_INVALID_PARAMETER; + } + if (StrCmp(Argv[1], L"-D") == 0) { + Status = DumpCapsule(); + CleanArg(); + return Status; + } + if (StrCmp(Argv[1], L"-U") == 0) { + Status = CreateMicrocodeFmp(); + CleanArg(); + return Status; + } + + Status = EFI_UNSUPPORTED; + CleanArg(); + + return Status; +} diff --git a/UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.inf b/UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.inf new file mode 100644 index 0000000..272e20e --- /dev/null +++ b/UefiCpuPkg/Application/MicrocodeCapsuleApp/MicrocodeCapsuleApp.inf @@ -0,0 +1,62 @@ +## @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.
+# 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 + +[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.
+// +// 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.
+// +// 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..b8c111d --- /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.
+ 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + 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 Microcode FMP capsule. + + @param Image The Microcode FMP capsule. + @param 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 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