From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id B78E981F0A for ; Wed, 30 Nov 2016 21:00:41 -0800 (PST) Received: from fmsmga005.fm.intel.com ([10.253.24.32]) by fmsmga101.fm.intel.com with ESMTP; 30 Nov 2016 21:00:41 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.33,723,1477983600"; d="scan'208";a="37647775" Received: from fmsmsx103.amr.corp.intel.com ([10.18.124.201]) by fmsmga005.fm.intel.com with ESMTP; 30 Nov 2016 21:00:41 -0800 Received: from shsmsx104.ccr.corp.intel.com (10.239.4.70) by FMSMSX103.amr.corp.intel.com (10.18.124.201) with Microsoft SMTP Server (TLS) id 14.3.248.2; Wed, 30 Nov 2016 21:00:40 -0800 Received: from shsmsx102.ccr.corp.intel.com ([169.254.2.239]) by SHSMSX104.ccr.corp.intel.com ([169.254.5.142]) with mapi id 14.03.0248.002; Thu, 1 Dec 2016 13:00:38 +0800 From: "Fan, Jeff" To: "Yao, Jiewen" , "edk2-devel@lists.01.org" CC: "Dong, Eric" Thread-Topic: [PATCH] MdeModulePkg/CapsuleApp: Add Fmp->GetImage() support. Thread-Index: AQHSSkY/96zt9c7JUkCupZdTIi4ig6DyitYQ Date: Thu, 1 Dec 2016 05:00:38 +0000 Message-ID: <542CF652F8836A4AB8DBFAAD40ED192A4A2ED3CD@shsmsx102.ccr.corp.intel.com> References: <1480426851-44132-1-git-send-email-jiewen.yao@intel.com> In-Reply-To: <1480426851-44132-1-git-send-email-jiewen.yao@intel.com> Accept-Language: zh-CN, en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-titus-metadata-40: eyJDYXRlZ29yeUxhYmVscyI6IiIsIk1ldGFkYXRhIjp7Im5zIjoiaHR0cDpcL1wvd3d3LnRpdHVzLmNvbVwvbnNcL0ludGVsMyIsImlkIjoiYmEyODA0NzYtM2Q5Ni00ODA1LWFiMTgtMGIyYTI3ZjAzZTVlIiwicHJvcHMiOlt7Im4iOiJDVFBDbGFzc2lmaWNhdGlvbiIsInZhbHMiOlt7InZhbHVlIjoiQ1RQX0lDIn1dfV19LCJTdWJqZWN0TGFiZWxzIjpbXSwiVE1DVmVyc2lvbiI6IjE1LjkuNi42IiwiVHJ1c3RlZExhYmVsSGFzaCI6Ik5qVmhqNGRJbXJYd1lqSzlRaWJRaWJka1FGUmxraUdHOTUrRDQ5SVN3ZWM9In0= x-ctpclassification: CTP_IC x-originating-ip: [10.239.127.40] MIME-Version: 1.0 Subject: Re: [PATCH] MdeModulePkg/CapsuleApp: Add Fmp->GetImage() support. 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: Thu, 01 Dec 2016 05:00:41 -0000 Content-Language: en-US Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable Reviewed-by: Jeff Fan -----Original Message----- From: Yao, Jiewen=20 Sent: Tuesday, November 29, 2016 9:41 PM To: edk2-devel@lists.01.org Cc: Dong, Eric; Fan, Jeff Subject: [PATCH] MdeModulePkg/CapsuleApp: Add Fmp->GetImage() support. We add Fmp->GetImage() support in CapsuleApp. So that user may call Fmp->GetImage() in UEFI shell environment. This is useful to do unit test for FMP which supports GetImage(), or user w= ants to get current image, such as Microcode. Cc: Eric Dong Cc: Jeff Fan Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Jiewen Yao --- MdeModulePkg/Application/CapsuleApp/AppSupport.c | 141 +++++++++++++ Mde= ModulePkg/Application/CapsuleApp/CapsuleApp.c | 57 +++++- MdeModulePkg/A= pplication/CapsuleApp/CapsuleDump.c | 214 ++++++++++++++++++++ 3 files changed, 411 insertions(+), 1 deletion(-) diff --git a/MdeModulePkg/Application/CapsuleApp/AppSupport.c b/MdeModulePk= g/Application/CapsuleApp/AppSupport.c index 0a1224d..6aea76a 100644 --- a/MdeModulePkg/Application/CapsuleApp/AppSupport.c +++ b/MdeModulePkg/Application/CapsuleApp/AppSupport.c @@ -27,6 +27,9 @@ #include #include =20 +#define IS_HYPHEN(a) ((a) =3D=3D L'-') +#define IS_NULL(a) ((a) =3D=3D L'\0') + #define MAX_ARG_NUM 11 =20 UINTN Argc; @@ -61,6 +64,144 @@ GetArg ( } =20 /** + Converts a list of string to a specified buffer. + + @param[out] Buf The output buffer that contains the string. + @param[in] BufferLength The length of the buffer + @param[in] Str The input string that contains the hex numbe= r + + @retval EFI_SUCCESS The string was successfully converted to the buff= er. + +**/ +EFI_STATUS +StrToBuf ( + OUT UINT8 *Buf, + IN UINTN BufferLength, + IN CHAR16 *Str + ) +{ + UINTN Index; + UINTN StrLength; + UINT8 Digit; + UINT8 Byte; + + Digit =3D 0; + + // + // Two hex char make up one byte + // + StrLength =3D BufferLength * sizeof (CHAR16); + + for(Index =3D 0; Index < StrLength; Index++, Str++) { + + if ((*Str >=3D L'a') && (*Str <=3D L'f')) { + Digit =3D (UINT8) (*Str - L'a' + 0x0A); + } else if ((*Str >=3D L'A') && (*Str <=3D L'F')) { + Digit =3D (UINT8) (*Str - L'A' + 0x0A); + } else if ((*Str >=3D L'0') && (*Str <=3D L'9')) { + Digit =3D (UINT8) (*Str - L'0'); + } else { + return EFI_INVALID_PARAMETER; + } + + // + // For odd characters, write the upper nibble for each buffer byte, + // and for even characters, the lower nibble. + // + if ((Index & 1) =3D=3D 0) { + Byte =3D (UINT8) (Digit << 4); + } else { + Byte =3D Buf[Index / 2]; + Byte &=3D 0xF0; + Byte =3D (UINT8) (Byte | Digit); + } + + Buf[Index / 2] =3D Byte; + } + + return EFI_SUCCESS; +} + +/** + Converts a string to GUID value. + Guid Format is xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + + @param[in] Str The registry format GUID string that contai= ns the GUID value. + @param[out] Guid A pointer to the converted GUID value. + + @retval EFI_SUCCESS The GUID string was successfully converted to th= e GUID value. + @retval EFI_UNSUPPORTED The input string is not in registry format. + @return others Some error occurred when converting part of GUID= value. + +**/ +EFI_STATUS +StrToGuid ( + IN CHAR16 *Str, + OUT EFI_GUID *Guid + ) +{ + // + // Get the first UINT32 data + // + Guid->Data1 =3D (UINT32) StrHexToUint64 (Str); + while (!IS_HYPHEN (*Str) && !IS_NULL (*Str)) { + Str ++; + } + + if (IS_HYPHEN (*Str)) { + Str++; + } else { + return EFI_UNSUPPORTED; + } + + // + // Get the second UINT16 data + // + Guid->Data2 =3D (UINT16) StrHexToUint64 (Str); while (!IS_HYPHEN=20 + (*Str) && !IS_NULL (*Str)) { + Str ++; + } + + if (IS_HYPHEN (*Str)) { + Str++; + } else { + return EFI_UNSUPPORTED; + } + + // + // Get the third UINT16 data + // + Guid->Data3 =3D (UINT16) StrHexToUint64 (Str); while (!IS_HYPHEN=20 + (*Str) && !IS_NULL (*Str)) { + Str ++; + } + + if (IS_HYPHEN (*Str)) { + Str++; + } else { + return EFI_UNSUPPORTED; + } + + // + // Get the following 8 bytes data + // + StrToBuf (&Guid->Data4[0], 2, Str); + // + // Skip 2 byte hex chars + // + Str +=3D 2 * 2; + + if (IS_HYPHEN (*Str)) { + Str++; + } else { + return EFI_UNSUPPORTED; + } + StrToBuf (&Guid->Data4[2], 6, Str); + + return EFI_SUCCESS; +} + +/** Return File System Volume containing this shell application. =20 @return File System Volume containing this shell application. diff --git a/MdeModulePkg/Application/CapsuleApp/CapsuleApp.c b/MdeModulePk= g/Application/CapsuleApp/CapsuleApp.c index 23672ae..5137259 100644 --- a/MdeModulePkg/Application/CapsuleApp/CapsuleApp.c +++ b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.c @@ -86,6 +86,22 @@ DumpFmpData ( ); =20 /** + Dump FMP image data. + + @param[in] ImageTypeId The ImageTypeId of the FMP image. + It is used to identify the FMP protocol. + @param[in] ImageIndex The ImageIndex of the FMP image. + It is the input parameter for FMP->GetImage(). + @param[in] ImageName The file name to hold the output FMP image. +**/ +VOID +DumpFmpImage ( + IN EFI_GUID *ImageTypeId, + IN UINTN ImageIndex, + IN CHAR16 *ImageName + ); + +/** Dump ESRT info. **/ VOID @@ -127,6 +143,24 @@ WriteFileFromBuffer ( ); =20 /** + Converts a string to GUID value. + Guid Format is xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + + @param[in] Str The registry format GUID string that contai= ns the GUID value. + @param[out] Guid A pointer to the converted GUID value. + + @retval EFI_SUCCESS The GUID string was successfully converted to th= e GUID value. + @retval EFI_UNSUPPORTED The input string is not in registry format. + @return others Some error occurred when converting part of GUID= value. + +**/ +EFI_STATUS +StrToGuid ( + IN CHAR16 *Str, + OUT EFI_GUID *Guid + ); + +/** =20 This function parse application ARG. =20 @@ -662,6 +696,7 @@ PrintUsage ( Print(L" CapsuleApp -G -O \n"); Print(L" CapsuleApp -N -O \n"); Print(L" CapsuleApp -D \n"); + Print(L" CapsuleApp -P GET -O \n"); Print(L"Parameter:\n"); Print(L" -S: Dump capsule report variable (EFI_CAPSULE_REPORT_GUID),\n= "); Print(L" which is defined in UEFI specification.\n"); @@ -737,7 +772,27 @@ UefiMain ( return Status; } if (StrCmp(Argv[1], L"-P") =3D=3D 0) { - DumpFmpData(); + if (Argc =3D=3D 2) { + DumpFmpData(); + } + if (Argc >=3D 3) { + if (StrCmp(Argv[2], L"GET") =3D=3D 0) { + EFI_GUID ImageTypeId; + UINTN ImageIndex; + // + // FMP->GetImage() + // + Status =3D StrToGuid(Argv[3], &ImageTypeId); + if (EFI_ERROR(Status)) { + Print (L"Invalid ImageTypeId - %s\n", Argv[3]); + return Status; + } + ImageIndex =3D StrDecimalToUintn(Argv[4]); + if (StrCmp(Argv[5], L"-O") =3D=3D 0) { + DumpFmpImage(&ImageTypeId, ImageIndex, Argv[6]); + } + } + } return EFI_SUCCESS; } if (StrCmp(Argv[1], L"-E") =3D=3D 0) { diff --git a/MdeModulePkg/Application/CapsuleApp/CapsuleDump.c b/MdeModuleP= kg/Application/CapsuleApp/CapsuleDump.c index d09b938..3d83ec4 100644 --- a/MdeModulePkg/Application/CapsuleApp/CapsuleDump.c +++ b/MdeModulePkg/Application/CapsuleApp/CapsuleDump.c @@ -46,6 +46,22 @@ ReadFileToBuffer ( ); =20 /** + 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 + ); + +/** Dump UX capsule information. =20 @param[in] CapsuleHeader The UX capsule header @@ -738,3 +754,201 @@ DumpFmpData ( EXIT: FreePool(HandleBuffer); } + +/** + Check if the ImageInfo includes the ImageTypeId. + + @param[in] ImageInfo A pointer to EFI_FIRMWARE_IMAGE_DESCRIPTO= R. + @param[in] DescriptorCount The count of EFI_FIRMWARE_IMAGE_DESCRIPTO= R. + @param[in] DescriptorSize The size of an individual EFI_FIRMWARE_IM= AGE_DESCRIPTOR, in bytes. + @param[in] ImageTypeId A unique GUID identifying the firmware im= age type. + + @return TRUE This ImageInfo includes the ImageTypeId + @return FALSE This ImageInfo does not include the ImageTypeId **/=20 +BOOLEAN IsThisFmpImageInfo ( + IN EFI_FIRMWARE_IMAGE_DESCRIPTOR *ImageInfo, + IN UINT8 DescriptorCount, + IN UINTN DescriptorSize, + IN EFI_GUID *ImageTypeId + ) +{ + EFI_FIRMWARE_IMAGE_DESCRIPTOR *CurrentImageInfo; + UINTN Index; + + CurrentImageInfo =3D ImageInfo; + for (Index =3D 0; Index < DescriptorCount; Index++) { + if (CompareGuid (&CurrentImageInfo->ImageTypeId, ImageTypeId)) { + return TRUE; + } + CurrentImageInfo =3D (EFI_FIRMWARE_IMAGE_DESCRIPTOR *)((UINT8=20 +*)CurrentImageInfo + DescriptorSize); + } + return FALSE; +} + +/** + return the FMP whoes ImageInfo includes the ImageTypeId. + + @param[in] ImageTypeId A unique GUID identifying the firmware im= age type. + + @return The FMP whoes ImageInfo includes the ImageTypeId **/=20 +EFI_FIRMWARE_MANAGEMENT_PROTOCOL * FindFmpFromImageTypeId ( + IN EFI_GUID *ImageTypeId + ) +{ + EFI_STATUS Status; + EFI_FIRMWARE_MANAGEMENT_PROTOCOL *Fmp; + EFI_FIRMWARE_MANAGEMENT_PROTOCOL *TargetFmp; + EFI_HANDLE *HandleBuffer; + UINTN NumberOfHandles; + UINTN Index; + EFI_FIRMWARE_IMAGE_DESCRIPTOR *FmpImageInfoBuf; + UINTN ImageInfoSize; + UINT32 FmpImageInfoDescriptorVer; + UINT8 FmpImageInfoCount; + UINTN DescriptorSize; + UINT32 PackageVersion; + CHAR16 *PackageVersionName; + + Status =3D gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiFirmwareManagementProtocolGuid, + NULL, + &NumberOfHandles, + &HandleBuffer + ); + if (EFI_ERROR(Status)) { + Print(L"FMP protocol - %r\n", EFI_NOT_FOUND); + return NULL; + } + + TargetFmp =3D NULL; + for (Index =3D 0; Index < NumberOfHandles; Index++) { + Status =3D gBS->HandleProtocol( + HandleBuffer[Index], + &gEfiFirmwareManagementProtocolGuid, + (VOID **)&Fmp + ); + if (EFI_ERROR(Status)) { + continue; + } + + ImageInfoSize =3D 0; + Status =3D Fmp->GetImageInfo ( + Fmp, + &ImageInfoSize, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL + ); + if (Status !=3D EFI_BUFFER_TOO_SMALL) { + continue; + } + + FmpImageInfoBuf =3D NULL; + FmpImageInfoBuf =3D AllocateZeroPool (ImageInfoSize); + if (FmpImageInfoBuf =3D=3D NULL) { + FreePool(HandleBuffer); + Print(L"Out of resource\n"); + return NULL; + } + + PackageVersionName =3D NULL; + Status =3D 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)) { + FreePool(FmpImageInfoBuf); + continue; + } + + if (PackageVersionName !=3D NULL) { + FreePool(PackageVersionName); + } + + if (IsThisFmpImageInfo (FmpImageInfoBuf, FmpImageInfoCount, Descriptor= Size, ImageTypeId)) { + TargetFmp =3D Fmp; + } + FreePool(FmpImageInfoBuf); + if (TargetFmp !=3D NULL) { + break; + } + } + FreePool(HandleBuffer); + return TargetFmp; +} + +/** + Dump FMP image data. + + @param[in] ImageTypeId The ImageTypeId of the FMP image. + It is used to identify the FMP protocol. + @param[in] ImageIndex The ImageIndex of the FMP image. + It is the input parameter for FMP->GetImage(). + @param[in] ImageName The file name to hold the output FMP image. +**/ +VOID +DumpFmpImage ( + IN EFI_GUID *ImageTypeId, + IN UINTN ImageIndex, + IN CHAR16 *ImageName + ) +{ + EFI_STATUS Status; + EFI_FIRMWARE_MANAGEMENT_PROTOCOL *Fmp; + VOID *Image; + UINTN ImageSize; + + Fmp =3D FindFmpFromImageTypeId (ImageTypeId); if (Fmp =3D=3D NULL) { + Print(L"No FMP include ImageTypeId %g\n", ImageTypeId); + return ; + } + + if (ImageIndex > 0xFF) { + Print(L"ImageIndex 0x%x too big\n", ImageIndex); + return ; + } + + Image =3D Fmp; + ImageSize =3D 0; + Status =3D Fmp->GetImage (Fmp, (UINT8)ImageIndex, Image, &ImageSize); =20 + if (Status !=3D EFI_BUFFER_TOO_SMALL) { + Print(L"Fmp->GetImage - %r\n", Status); + return ; + } + + Image =3D AllocatePool (ImageSize); + if (Image =3D=3D NULL) { + Print(L"Allocate FmpImage 0x%x - %r\n", ImageSize, EFI_OUT_OF_RESOURCE= S); + return ; + } + + Status =3D Fmp->GetImage (Fmp, (UINT8)ImageIndex, Image, &ImageSize); =20 + if (EFI_ERROR(Status)) { + Print(L"Fmp->GetImage - %r\n", Status); + return ; + } + + Status =3D WriteFileFromBuffer(ImageName, ImageSize, Image); + Print(L"CapsuleApp: Dump %g ImageIndex (0x%x) to %s %r\n",=20 + ImageTypeId, ImageIndex, ImageName, Status); + + return ; +} -- 2.7.4.windows.1