#include <Guid/FileInfo.h>\r
#include <Guid/Gpt.h>\r
\r
+#define IS_HYPHEN(a) ((a) == L'-')\r
+#define IS_NULL(a) ((a) == L'\0')\r
+\r
#define MAX_ARG_NUM 11\r
\r
UINTN Argc;\r
return EFI_SUCCESS;\r
}\r
\r
+/**\r
+ Converts a list of string to a specified buffer.\r
+\r
+ @param[out] Buf The output buffer that contains the string.\r
+ @param[in] BufferLength The length of the buffer\r
+ @param[in] Str The input string that contains the hex number\r
+\r
+ @retval EFI_SUCCESS The string was successfully converted to the buffer.\r
+\r
+**/\r
+EFI_STATUS\r
+StrToBuf (\r
+ OUT UINT8 *Buf,\r
+ IN UINTN BufferLength,\r
+ IN CHAR16 *Str\r
+ )\r
+{\r
+ UINTN Index;\r
+ UINTN StrLength;\r
+ UINT8 Digit;\r
+ UINT8 Byte;\r
+\r
+ Digit = 0;\r
+\r
+ //\r
+ // Two hex char make up one byte\r
+ //\r
+ StrLength = BufferLength * sizeof (CHAR16);\r
+\r
+ for(Index = 0; Index < StrLength; Index++, Str++) {\r
+\r
+ if ((*Str >= L'a') && (*Str <= L'f')) {\r
+ Digit = (UINT8) (*Str - L'a' + 0x0A);\r
+ } else if ((*Str >= L'A') && (*Str <= L'F')) {\r
+ Digit = (UINT8) (*Str - L'A' + 0x0A);\r
+ } else if ((*Str >= L'0') && (*Str <= L'9')) {\r
+ Digit = (UINT8) (*Str - L'0');\r
+ } else {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // For odd characters, write the upper nibble for each buffer byte,\r
+ // and for even characters, the lower nibble.\r
+ //\r
+ if ((Index & 1) == 0) {\r
+ Byte = (UINT8) (Digit << 4);\r
+ } else {\r
+ Byte = Buf[Index / 2];\r
+ Byte &= 0xF0;\r
+ Byte = (UINT8) (Byte | Digit);\r
+ }\r
+\r
+ Buf[Index / 2] = Byte;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Converts a string to GUID value.\r
+ Guid Format is xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\r
+\r
+ @param[in] Str The registry format GUID string that contains the GUID value.\r
+ @param[out] Guid A pointer to the converted GUID value.\r
+\r
+ @retval EFI_SUCCESS The GUID string was successfully converted to the GUID value.\r
+ @retval EFI_UNSUPPORTED The input string is not in registry format.\r
+ @return others Some error occurred when converting part of GUID value.\r
+\r
+**/\r
+EFI_STATUS\r
+StrToGuid (\r
+ IN CHAR16 *Str,\r
+ OUT EFI_GUID *Guid\r
+ )\r
+{\r
+ //\r
+ // Get the first UINT32 data\r
+ //\r
+ Guid->Data1 = (UINT32) StrHexToUint64 (Str);\r
+ while (!IS_HYPHEN (*Str) && !IS_NULL (*Str)) {\r
+ Str ++;\r
+ }\r
+\r
+ if (IS_HYPHEN (*Str)) {\r
+ Str++;\r
+ } else {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ //\r
+ // Get the second UINT16 data\r
+ //\r
+ Guid->Data2 = (UINT16) StrHexToUint64 (Str);\r
+ while (!IS_HYPHEN (*Str) && !IS_NULL (*Str)) {\r
+ Str ++;\r
+ }\r
+\r
+ if (IS_HYPHEN (*Str)) {\r
+ Str++;\r
+ } else {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ //\r
+ // Get the third UINT16 data\r
+ //\r
+ Guid->Data3 = (UINT16) StrHexToUint64 (Str);\r
+ while (!IS_HYPHEN (*Str) && !IS_NULL (*Str)) {\r
+ Str ++;\r
+ }\r
+\r
+ if (IS_HYPHEN (*Str)) {\r
+ Str++;\r
+ } else {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ //\r
+ // Get the following 8 bytes data\r
+ //\r
+ StrToBuf (&Guid->Data4[0], 2, Str);\r
+ //\r
+ // Skip 2 byte hex chars\r
+ //\r
+ Str += 2 * 2;\r
+\r
+ if (IS_HYPHEN (*Str)) {\r
+ Str++;\r
+ } else {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ StrToBuf (&Guid->Data4[2], 6, Str);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
/**\r
Return File System Volume containing this shell application.\r
\r
VOID\r
);\r
\r
+/**\r
+ Dump FMP image data.\r
+\r
+ @param[in] ImageTypeId The ImageTypeId of the FMP image.\r
+ It is used to identify the FMP protocol.\r
+ @param[in] ImageIndex The ImageIndex of the FMP image.\r
+ It is the input parameter for FMP->GetImage().\r
+ @param[in] ImageName The file name to hold the output FMP image.\r
+**/\r
+VOID\r
+DumpFmpImage (\r
+ IN EFI_GUID *ImageTypeId,\r
+ IN UINTN ImageIndex,\r
+ IN CHAR16 *ImageName\r
+ );\r
+\r
/**\r
Dump ESRT info.\r
**/\r
IN VOID *Buffer\r
);\r
\r
+/**\r
+ Converts a string to GUID value.\r
+ Guid Format is xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\r
+\r
+ @param[in] Str The registry format GUID string that contains the GUID value.\r
+ @param[out] Guid A pointer to the converted GUID value.\r
+\r
+ @retval EFI_SUCCESS The GUID string was successfully converted to the GUID value.\r
+ @retval EFI_UNSUPPORTED The input string is not in registry format.\r
+ @return others Some error occurred when converting part of GUID value.\r
+\r
+**/\r
+EFI_STATUS\r
+StrToGuid (\r
+ IN CHAR16 *Str,\r
+ OUT EFI_GUID *Guid\r
+ );\r
+\r
/**\r
\r
This function parse application ARG.\r
Print(L" CapsuleApp -G <BMP> -O <Capsule>\n");\r
Print(L" CapsuleApp -N <Capsule> -O <NestedCapsule>\n");\r
Print(L" CapsuleApp -D <Capsule>\n");\r
+ Print(L" CapsuleApp -P GET <ImageTypeId> <Index> -O <FileName>\n");\r
Print(L"Parameter:\n");\r
Print(L" -S: Dump capsule report variable (EFI_CAPSULE_REPORT_GUID),\n");\r
Print(L" which is defined in UEFI specification.\n");\r
return Status;\r
}\r
if (StrCmp(Argv[1], L"-P") == 0) {\r
- DumpFmpData();\r
+ if (Argc == 2) {\r
+ DumpFmpData();\r
+ }\r
+ if (Argc >= 3) {\r
+ if (StrCmp(Argv[2], L"GET") == 0) {\r
+ EFI_GUID ImageTypeId;\r
+ UINTN ImageIndex;\r
+ //\r
+ // FMP->GetImage()\r
+ //\r
+ Status = StrToGuid(Argv[3], &ImageTypeId);\r
+ if (EFI_ERROR(Status)) {\r
+ Print (L"Invalid ImageTypeId - %s\n", Argv[3]);\r
+ return Status;\r
+ }\r
+ ImageIndex = StrDecimalToUintn(Argv[4]);\r
+ if (StrCmp(Argv[5], L"-O") == 0) {\r
+ DumpFmpImage(&ImageTypeId, ImageIndex, Argv[6]);\r
+ }\r
+ }\r
+ }\r
return EFI_SUCCESS;\r
}\r
if (StrCmp(Argv[1], L"-E") == 0) {\r
OUT VOID **Buffer\r
);\r
\r
+/**\r
+ Write a file.\r
+\r
+ @param[in] FileName The file to be written.\r
+ @param[in] BufferSize The file buffer size\r
+ @param[in] Buffer The file buffer\r
+\r
+ @retval EFI_SUCCESS Write file successfully\r
+**/\r
+EFI_STATUS\r
+WriteFileFromBuffer (\r
+ IN CHAR16 *FileName,\r
+ IN UINTN BufferSize,\r
+ IN VOID *Buffer\r
+ );\r
+\r
/**\r
Dump UX capsule information.\r
\r
EXIT:\r
FreePool(HandleBuffer);\r
}\r
+\r
+/**\r
+ Check if the ImageInfo includes the ImageTypeId.\r
+\r
+ @param[in] ImageInfo A pointer to EFI_FIRMWARE_IMAGE_DESCRIPTOR.\r
+ @param[in] DescriptorCount The count of EFI_FIRMWARE_IMAGE_DESCRIPTOR.\r
+ @param[in] DescriptorSize The size of an individual EFI_FIRMWARE_IMAGE_DESCRIPTOR, in bytes.\r
+ @param[in] ImageTypeId A unique GUID identifying the firmware image type.\r
+\r
+ @return TRUE This ImageInfo includes the ImageTypeId\r
+ @return FALSE This ImageInfo does not include the ImageTypeId\r
+**/\r
+BOOLEAN\r
+IsThisFmpImageInfo (\r
+ IN EFI_FIRMWARE_IMAGE_DESCRIPTOR *ImageInfo,\r
+ IN UINT8 DescriptorCount,\r
+ IN UINTN DescriptorSize,\r
+ IN EFI_GUID *ImageTypeId\r
+ )\r
+{\r
+ EFI_FIRMWARE_IMAGE_DESCRIPTOR *CurrentImageInfo;\r
+ UINTN Index;\r
+\r
+ CurrentImageInfo = ImageInfo;\r
+ for (Index = 0; Index < DescriptorCount; Index++) {\r
+ if (CompareGuid (&CurrentImageInfo->ImageTypeId, ImageTypeId)) {\r
+ return TRUE;\r
+ }\r
+ CurrentImageInfo = (EFI_FIRMWARE_IMAGE_DESCRIPTOR *)((UINT8 *)CurrentImageInfo + DescriptorSize);\r
+ }\r
+ return FALSE;\r
+}\r
+\r
+/**\r
+ return the FMP whoes ImageInfo includes the ImageTypeId.\r
+\r
+ @param[in] ImageTypeId A unique GUID identifying the firmware image type.\r
+\r
+ @return The FMP whoes ImageInfo includes the ImageTypeId\r
+**/\r
+EFI_FIRMWARE_MANAGEMENT_PROTOCOL *\r
+FindFmpFromImageTypeId (\r
+ IN EFI_GUID *ImageTypeId\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_FIRMWARE_MANAGEMENT_PROTOCOL *Fmp;\r
+ EFI_FIRMWARE_MANAGEMENT_PROTOCOL *TargetFmp;\r
+ EFI_HANDLE *HandleBuffer;\r
+ UINTN NumberOfHandles;\r
+ UINTN Index;\r
+ EFI_FIRMWARE_IMAGE_DESCRIPTOR *FmpImageInfoBuf;\r
+ UINTN ImageInfoSize;\r
+ UINT32 FmpImageInfoDescriptorVer;\r
+ UINT8 FmpImageInfoCount;\r
+ UINTN DescriptorSize;\r
+ UINT32 PackageVersion;\r
+ CHAR16 *PackageVersionName;\r
+\r
+ Status = gBS->LocateHandleBuffer (\r
+ ByProtocol,\r
+ &gEfiFirmwareManagementProtocolGuid,\r
+ NULL,\r
+ &NumberOfHandles,\r
+ &HandleBuffer\r
+ );\r
+ if (EFI_ERROR(Status)) {\r
+ Print(L"FMP protocol - %r\n", EFI_NOT_FOUND);\r
+ return NULL;\r
+ }\r
+\r
+ TargetFmp = NULL;\r
+ for (Index = 0; Index < NumberOfHandles; Index++) {\r
+ Status = gBS->HandleProtocol(\r
+ HandleBuffer[Index],\r
+ &gEfiFirmwareManagementProtocolGuid,\r
+ (VOID **)&Fmp\r
+ );\r
+ if (EFI_ERROR(Status)) {\r
+ continue;\r
+ }\r
+\r
+ ImageInfoSize = 0;\r
+ Status = Fmp->GetImageInfo (\r
+ Fmp,\r
+ &ImageInfoSize,\r
+ NULL,\r
+ NULL,\r
+ NULL,\r
+ NULL,\r
+ NULL,\r
+ NULL\r
+ );\r
+ if (Status != EFI_BUFFER_TOO_SMALL) {\r
+ continue;\r
+ }\r
+\r
+ FmpImageInfoBuf = NULL;\r
+ FmpImageInfoBuf = AllocateZeroPool (ImageInfoSize);\r
+ if (FmpImageInfoBuf == NULL) {\r
+ FreePool(HandleBuffer);\r
+ Print(L"Out of resource\n");\r
+ return NULL;\r
+ }\r
+\r
+ PackageVersionName = NULL;\r
+ Status = Fmp->GetImageInfo (\r
+ Fmp,\r
+ &ImageInfoSize, // ImageInfoSize\r
+ FmpImageInfoBuf, // ImageInfo\r
+ &FmpImageInfoDescriptorVer, // DescriptorVersion\r
+ &FmpImageInfoCount, // DescriptorCount\r
+ &DescriptorSize, // DescriptorSize\r
+ &PackageVersion, // PackageVersion\r
+ &PackageVersionName // PackageVersionName\r
+ );\r
+\r
+ //\r
+ // If FMP GetInformation interface failed, skip this resource\r
+ //\r
+ if (EFI_ERROR(Status)) {\r
+ FreePool(FmpImageInfoBuf);\r
+ continue;\r
+ }\r
+\r
+ if (PackageVersionName != NULL) {\r
+ FreePool(PackageVersionName);\r
+ }\r
+\r
+ if (IsThisFmpImageInfo (FmpImageInfoBuf, FmpImageInfoCount, DescriptorSize, ImageTypeId)) {\r
+ TargetFmp = Fmp;\r
+ }\r
+ FreePool(FmpImageInfoBuf);\r
+ if (TargetFmp != NULL) {\r
+ break;\r
+ }\r
+ }\r
+ FreePool(HandleBuffer);\r
+ return TargetFmp;\r
+}\r
+\r
+/**\r
+ Dump FMP image data.\r
+\r
+ @param[in] ImageTypeId The ImageTypeId of the FMP image.\r
+ It is used to identify the FMP protocol.\r
+ @param[in] ImageIndex The ImageIndex of the FMP image.\r
+ It is the input parameter for FMP->GetImage().\r
+ @param[in] ImageName The file name to hold the output FMP image.\r
+**/\r
+VOID\r
+DumpFmpImage (\r
+ IN EFI_GUID *ImageTypeId,\r
+ IN UINTN ImageIndex,\r
+ IN CHAR16 *ImageName\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_FIRMWARE_MANAGEMENT_PROTOCOL *Fmp;\r
+ VOID *Image;\r
+ UINTN ImageSize;\r
+\r
+ Fmp = FindFmpFromImageTypeId (ImageTypeId);\r
+ if (Fmp == NULL) {\r
+ Print(L"No FMP include ImageTypeId %g\n", ImageTypeId);\r
+ return ;\r
+ }\r
+\r
+ if (ImageIndex > 0xFF) {\r
+ Print(L"ImageIndex 0x%x too big\n", ImageIndex);\r
+ return ;\r
+ }\r
+\r
+ Image = Fmp;\r
+ ImageSize = 0;\r
+ Status = Fmp->GetImage (Fmp, (UINT8)ImageIndex, Image, &ImageSize);\r
+ if (Status != EFI_BUFFER_TOO_SMALL) {\r
+ Print(L"Fmp->GetImage - %r\n", Status);\r
+ return ;\r
+ }\r
+\r
+ Image = AllocatePool (ImageSize);\r
+ if (Image == NULL) {\r
+ Print(L"Allocate FmpImage 0x%x - %r\n", ImageSize, EFI_OUT_OF_RESOURCES);\r
+ return ;\r
+ }\r
+\r
+ Status = Fmp->GetImage (Fmp, (UINT8)ImageIndex, Image, &ImageSize);\r
+ if (EFI_ERROR(Status)) {\r
+ Print(L"Fmp->GetImage - %r\n", Status);\r
+ return ;\r
+ }\r
+\r
+ Status = WriteFileFromBuffer(ImageName, ImageSize, Image);\r
+ Print(L"CapsuleApp: Dump %g ImageIndex (0x%x) to %s %r\n", ImageTypeId, ImageIndex, ImageName, Status);\r
+\r
+ return ;\r
+}\r