X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=MdeModulePkg%2FApplication%2FCapsuleApp%2FCapsuleApp.c;h=4d907242f38b55d441fdad8dacc34dc454f83446;hb=131818ba5a83d1e8f3f1b4c041200755fff64abb;hp=6febe846b1406f1f9098114061b3ccd95877dd09;hpb=7043a90eee1150db1d55cdde2a98700fa10838e5;p=mirror_edk2.git diff --git a/MdeModulePkg/Application/CapsuleApp/CapsuleApp.c b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.c index 6febe846b1..4d907242f3 100644 --- a/MdeModulePkg/Application/CapsuleApp/CapsuleApp.c +++ b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.c @@ -1,7 +1,7 @@ /** @file A shell application that triggers capsule update process. - Copyright (c) 2016 - 2017, Intel Corporation. All rights reserved.
+ Copyright (c) 2016 - 2018, 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 @@ -21,12 +21,8 @@ #include #include #include -#include -#include +#include #include -#include -#include -#include #include #include #include @@ -73,7 +69,7 @@ DumpCapsule ( @retval EFI_UNSUPPORTED Input parameter is not valid. **/ EFI_STATUS -DmpCapsuleStatusVariable ( +DumpCapsuleStatusVariable ( VOID ); @@ -117,7 +113,8 @@ DumpEsrtData ( @param[out] Buffer The file buffer @retval EFI_SUCCESS Read file successfully - @retval EFI_NOT_FOUND File not found + @retval EFI_NOT_FOUND Shell protocol or file not found + @retval others Read file failed **/ EFI_STATUS ReadFileToBuffer ( @@ -134,6 +131,8 @@ ReadFileToBuffer ( @param[in] Buffer The file buffer @retval EFI_SUCCESS Write file successfully + @retval EFI_NOT_FOUND Shell protocol not found + @retval others Write file failed **/ EFI_STATUS WriteFileFromBuffer ( @@ -174,20 +173,26 @@ CreateBmpFmp ( EFI_DISPLAY_CAPSULE *DisplayCapsule; EFI_STATUS Status; EFI_GRAPHICS_OUTPUT_PROTOCOL *Gop; + EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL *GopBlt; + UINTN GopBltSize; + UINTN Height; + UINTN Width; Status = gBS->LocateProtocol(&gEfiGraphicsOutputProtocolGuid, NULL, (VOID **)&Gop); if (EFI_ERROR(Status)) { Print(L"CapsuleApp: NO GOP is found.\n"); return EFI_UNSUPPORTED; } + Info = Gop->Mode->Info; 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); + Print(L"HorizontalResolution - %d, ", Info->HorizontalResolution); + Print(L"VerticalResolution - %d\n", Info->VerticalResolution); // HorizontalResolution >= BMP_IMAGE_HEADER.PixelWidth // VerticalResolution >= BMP_IMAGE_HEADER.PixelHeight if (Argc != 5) { - Print(L"CapsuleApp: Invalid Parameter.\n"); + Print(L"CapsuleApp: Incorrect parameter count.\n"); return EFI_UNSUPPORTED; } @@ -208,6 +213,35 @@ CreateBmpFmp ( goto Done; } + GopBlt = NULL; + Status = TranslateBmpToGopBlt ( + BmpBuffer, + FileSize, + &GopBlt, + &GopBltSize, + &Height, + &Width + ); + if (EFI_ERROR(Status)) { + Print(L"CapsuleApp: BMP image (%s) is not valid.\n", BmpName); + goto Done; + } + if (GopBlt != NULL) { + FreePool (GopBlt); + } + Print(L"BMP image (%s), Width - %d, Height - %d\n", BmpName, Width, Height); + + if (Height > Info->VerticalResolution) { + Status = EFI_INVALID_PARAMETER; + Print(L"CapsuleApp: BMP image (%s) height is larger than current resolution.\n", BmpName); + goto Done; + } + if (Width > Info->HorizontalResolution) { + Status = EFI_INVALID_PARAMETER; + Print(L"CapsuleApp: BMP image (%s) width is larger than current resolution.\n", BmpName); + goto Done; + } + FullCapsuleBufferSize = sizeof(EFI_DISPLAY_CAPSULE) + FileSize; FullCapsuleBuffer = AllocatePool(FullCapsuleBufferSize); if (FullCapsuleBuffer == NULL) { @@ -227,8 +261,27 @@ CreateBmpFmp ( DisplayCapsule->ImagePayload.ImageType = 0; // BMP DisplayCapsule->ImagePayload.Reserved = 0; DisplayCapsule->ImagePayload.Mode = Gop->Mode->Mode; - DisplayCapsule->ImagePayload.OffsetX = 0; - DisplayCapsule->ImagePayload.OffsetY = 0; + + // + // Center the bitmap horizontally + // + DisplayCapsule->ImagePayload.OffsetX = (UINT32)((Info->HorizontalResolution - Width) / 2); + + // + // Put bitmap 3/4 down the display. If bitmap is too tall, then align bottom + // of bitmap at bottom of display. + // + DisplayCapsule->ImagePayload.OffsetY = + MIN ( + (UINT32)(Info->VerticalResolution - Height), + (UINT32)(((3 * Info->VerticalResolution) - (2 * Height)) / 4) + ); + + Print(L"BMP image (%s), OffsetX - %d, OffsetY - %d\n", + BmpName, + DisplayCapsule->ImagePayload.OffsetX, + DisplayCapsule->ImagePayload.OffsetY + ); CopyMem((DisplayCapsule + 1), BmpBuffer, FileSize); @@ -308,6 +361,60 @@ GetEsrtFwType ( return ESRT_FW_TYPE_UNKNOWN; } +/** + Validate if it is valid capsule header + + This function assumes the caller provided correct CapsuleHeader pointer + and CapsuleSize. + + This function validates the fields in EFI_CAPSULE_HEADER. + + @param[in] CapsuleHeader Points to a capsule header. + @param[in] CapsuleSize Size of the whole capsule image. + +**/ +BOOLEAN +IsValidCapsuleHeader ( + IN EFI_CAPSULE_HEADER *CapsuleHeader, + IN UINT64 CapsuleSize + ) +{ + if (CapsuleSize < sizeof (EFI_CAPSULE_HEADER)) { + return FALSE; + } + if (CapsuleHeader->CapsuleImageSize != CapsuleSize) { + return FALSE; + } + if (CapsuleHeader->HeaderSize > CapsuleHeader->CapsuleImageSize) { + return FALSE; + } + if (CapsuleHeader->HeaderSize < sizeof (EFI_CAPSULE_HEADER)) { + return FALSE; + } + + return TRUE; +} + +/** + Return if this CapsuleGuid is a FMP capsule GUID or not. + + @param[in] CapsuleGuid A pointer to EFI_GUID + + @retval TRUE It is a FMP capsule GUID. + @retval FALSE It is not a FMP capsule GUID. +**/ +BOOLEAN +IsFmpCapsuleGuid ( + IN EFI_GUID *CapsuleGuid + ) +{ + if (CompareGuid(&gEfiFmpCapsuleGuid, CapsuleGuid)) { + return TRUE; + } + + return FALSE; +} + /** Append a capsule header on top of current image. This function follows Windows UEFI Firmware Update Platform document. @@ -333,7 +440,7 @@ CreateNestedFmp ( EFI_STATUS Status; if (Argc != 5) { - Print(L"CapsuleApp: Invalid Parameter.\n"); + Print(L"CapsuleApp: Incorrect parameter count.\n"); return EFI_UNSUPPORTED; } @@ -353,15 +460,28 @@ CreateNestedFmp ( Print(L"CapsuleApp: Capsule image (%s) is not found.\n", CapsuleName); goto Done; } + if (!IsValidCapsuleHeader (CapsuleBuffer, FileSize)) { + Print(L"CapsuleApp: Capsule image (%s) is not a valid capsule.\n", CapsuleName); + Status = EFI_INVALID_PARAMETER; + goto Done; + } + + if (!IsFmpCapsuleGuid (&((EFI_CAPSULE_HEADER *) CapsuleBuffer)->CapsuleGuid)) { + Print(L"CapsuleApp: Capsule image (%s) is not a FMP capsule.\n", CapsuleName); + Status = EFI_INVALID_PARAMETER; + goto Done; + } ImageTypeId = GetCapsuleImageTypeId(CapsuleBuffer); if (ImageTypeId == NULL) { Print(L"CapsuleApp: Capsule ImageTypeId is not found.\n"); + Status = EFI_INVALID_PARAMETER; goto Done; } FwType = GetEsrtFwType(ImageTypeId); if ((FwType != ESRT_FW_TYPE_SYSTEMFIRMWARE) && (FwType != ESRT_FW_TYPE_DEVICEFIRMWARE)) { Print(L"CapsuleApp: Capsule FwType is invalid.\n"); + Status = EFI_INVALID_PARAMETER; goto Done; } @@ -377,7 +497,7 @@ CreateNestedFmp ( 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->Flags = (FwType == ESRT_FW_TYPE_SYSTEMFIRMWARE) ? SYSTEM_FIRMWARE_FLAG : DEVICE_FIRMWARE_FLAG; NestedCapsuleHeader->CapsuleImageSize = (UINT32)FullCapsuleBufferSize; CopyMem((UINT8 *)NestedCapsuleHeader + NestedCapsuleHeader->HeaderSize, CapsuleBuffer, FileSize); @@ -412,11 +532,13 @@ ClearCapsuleStatusVariable ( UINT32 Index; CHAR16 CapsuleVarName[20]; CHAR16 *TempVarName; + BOOLEAN Found; StrCpyS (CapsuleVarName, sizeof(CapsuleVarName)/sizeof(CapsuleVarName[0]), L"Capsule"); TempVarName = CapsuleVarName + StrLen (CapsuleVarName); Index = 0; + Found = FALSE; while (TRUE) { UnicodeSPrint (TempVarName, 5 * sizeof(CHAR16), L"%04x", Index); @@ -427,12 +549,15 @@ ClearCapsuleStatusVariable ( 0, (VOID *)NULL ); - if (EFI_ERROR(Status)) { + if (Status == EFI_NOT_FOUND) { // - // There is no capsule variables, quit + // There is no more capsule variables, quit // break; } + Found = TRUE; + + Print (L"Clear %s %r\n", CapsuleVarName, Status); Index++; if (Index > 0xFFFF) { @@ -440,6 +565,10 @@ ClearCapsuleStatusVariable ( } } + if (!Found) { + Print (L"No any Capsule#### variable found\n"); + } + return EFI_SUCCESS; } @@ -498,7 +627,7 @@ BuildGatherList ( 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); + Print (L"CapsuleApp: capsule data starts at 0x%X with size 0x%X\n", (UINTN) CapsuleBuffer[Index], FileSize[Index]); } // @@ -654,7 +783,7 @@ CleanGatherList ( break; } - TempBlockPtr2 = (VOID *) ((UINTN) TempBlockPtr->Union.ContinuationPointer); + TempBlockPtr2 = (VOID *) ((UINTN) TempBlockPtr[Index].Union.ContinuationPointer); FreePool(TempBlockPtr1); TempBlockPtr1 = TempBlockPtr2; } @@ -680,21 +809,26 @@ PrintUsage ( Print(L" CapsuleApp -D \n"); Print(L" CapsuleApp -P GET -O \n"); Print(L"Parameter:\n"); - Print(L" -NR: No reset will be triggered for the capsule\n"); - Print(L" with CAPSULE_FLAGS_PERSIST_ACROSS_RESET and without CAPSULE_FLAGS_INITIATE_RESET.\n"); + Print(L" -NR: No reset will be triggered for the capsule with\n"); + Print(L" CAPSULE_FLAGS_PERSIST_ACROSS_RESET and without\n"); + Print(L" CAPSULE_FLAGS_INITIATE_RESET.\n"); Print(L" -S: Dump capsule report variable (EFI_CAPSULE_REPORT_GUID),\n"); Print(L" which is defined in UEFI specification.\n"); - Print(L" -C: Clear capsule report variable (EFI_CAPSULE_RPORT_GUID),\n"); + Print(L" -C: Clear capsule report variable (EFI_CAPSULE_REPORT_GUID),\n"); Print(L" which is defined in UEFI specification.\n"); - Print(L" -P: Dump UEFI FMP protocol info.\n"); + Print(L" -P: Dump UEFI FMP protocol info, or get image with specified\n"); + Print(L" ImageTypeId and Index (decimal format) to a file if 'GET'\n"); + Print(L" option is used.\n"); Print(L" -E: Dump UEFI ESRT table info.\n"); - Print(L" -G: Convert a BMP file to be a UX capsule,\n"); + Print(L" -G: Convert a BMP file to be an UX capsule,\n"); Print(L" according to Windows Firmware Update document\n"); - Print(L" -N: Append a Capsule Header to an existing capsule image,\n"); + Print(L" -N: Append a Capsule Header to an existing FMP capsule image\n"); + Print(L" with its ImageTypeId supported by the system,\n"); Print(L" according to Windows Firmware Update document\n"); Print(L" -O: Output new Capsule file name\n"); - Print(L" -D: Dump Capsule image header information and FMP header information,\n"); - Print(L" if it is an FMP capsule.\n"); + Print(L" -D: Dump Capsule image header information, image payload\n"); + Print(L" information if it is an UX capsule and FMP header\n"); + Print(L" information if it is a FMP capsule.\n"); } /** @@ -704,7 +838,8 @@ PrintUsage ( @param[in] SystemTable The system table. @retval EFI_SUCCESS Command completed successfully. - @retval EFI_INVALID_PARAMETER Command usage error. + @retval EFI_UNSUPPORTED Command usage unsupported. + @retval EFI_INVALID_PARAMETER Command usage invalid. @retval EFI_NOT_FOUND The input file can't be found. **/ EFI_STATUS @@ -719,14 +854,16 @@ UefiMain ( 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; + EFI_CAPSULE_HEADER *CapsuleHeaderArray[MAX_CAPSULE_NUM + 1]; + UINT64 MaxCapsuleSize; + EFI_RESET_TYPE ResetType; + BOOLEAN NeedReset; + BOOLEAN NoReset; + CHAR16 *CapsuleName; + UINTN CapsuleNum; + UINTN Index; + EFI_GUID ImageTypeId; + UINTN ImageIndex; Status = GetArg(); if (EFI_ERROR(Status)) { @@ -735,9 +872,13 @@ UefiMain ( } if (Argc < 2) { PrintUsage(); - return EFI_INVALID_PARAMETER; + return EFI_UNSUPPORTED; } if (StrCmp(Argv[1], L"-D") == 0) { + if (Argc != 3) { + Print(L"CapsuleApp: Incorrect parameter count.\n"); + return EFI_UNSUPPORTED; + } Status = DumpCapsule(Argv[2]); return Status; } @@ -750,7 +891,7 @@ UefiMain ( return Status; } if (StrCmp(Argv[1], L"-S") == 0) { - Status = DmpCapsuleStatusVariable(); + Status = DumpCapsuleStatusVariable(); return EFI_SUCCESS; } if (StrCmp(Argv[1], L"-C") == 0) { @@ -762,9 +903,15 @@ UefiMain ( DumpFmpData(); } if (Argc >= 3) { - if (StrCmp(Argv[2], L"GET") == 0) { - EFI_GUID ImageTypeId; - UINTN ImageIndex; + if (StrCmp(Argv[2], L"GET") != 0) { + Print(L"CapsuleApp: Unrecognized option(%s).\n", Argv[2]); + return EFI_UNSUPPORTED; + } else { + if (Argc != 7) { + Print(L"CapsuleApp: Incorrect parameter count.\n"); + return EFI_UNSUPPORTED; + } + // // FMP->GetImage() // @@ -774,17 +921,26 @@ UefiMain ( return EFI_INVALID_PARAMETER; } ImageIndex = StrDecimalToUintn(Argv[4]); - if (StrCmp(Argv[5], L"-O") == 0) { - DumpFmpImage(&ImageTypeId, ImageIndex, Argv[6]); + if (StrCmp(Argv[5], L"-O") != 0) { + Print(L"CapsuleApp: NO output file name.\n"); + return EFI_UNSUPPORTED; } + DumpFmpImage(&ImageTypeId, ImageIndex, Argv[6]); } } return EFI_SUCCESS; } + if (StrCmp(Argv[1], L"-E") == 0) { DumpEsrtData(); return EFI_SUCCESS; } + + if (Argv[1][0] == L'-') { + Print(L"CapsuleApp: Unrecognized option(%s).\n", Argv[1]); + return EFI_UNSUPPORTED; + } + CapsuleFirstIndex = 1; NoReset = FALSE; if ((Argc > 1) && (StrCmp(Argv[Argc - 1], L"-NR") == 0)) { @@ -815,6 +971,10 @@ UefiMain ( Print(L"CapsuleApp: capsule image (%s) is not found.\n", CapsuleName); goto Done; } + if (!IsValidCapsuleHeader (CapsuleBuffer[Index], FileSize[Index])) { + Print(L"CapsuleApp: Capsule image (%s) is not a valid capsule.\n", CapsuleName); + return EFI_INVALID_PARAMETER; + } } //