From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: mx.groups.io; dkim=missing; spf=pass (domain: intel.com, ip: 134.134.136.126, mailfrom: wei6.xu@intel.com) Received: from mga18.intel.com (mga18.intel.com [134.134.136.126]) by groups.io with SMTP; Wed, 19 Jun 2019 00:55:06 -0700 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga008.fm.intel.com ([10.253.24.58]) by orsmga106.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 19 Jun 2019 00:55:05 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.63,392,1557212400"; d="scan'208";a="160294176" Received: from fmsmsx104.amr.corp.intel.com ([10.18.124.202]) by fmsmga008.fm.intel.com with ESMTP; 19 Jun 2019 00:55:04 -0700 Received: from shsmsx106.ccr.corp.intel.com (10.239.4.159) by fmsmsx104.amr.corp.intel.com (10.18.124.202) with Microsoft SMTP Server (TLS) id 14.3.439.0; Wed, 19 Jun 2019 00:55:04 -0700 Received: from shsmsx104.ccr.corp.intel.com ([169.254.5.185]) by SHSMSX106.ccr.corp.intel.com ([169.254.10.89]) with mapi id 14.03.0439.000; Wed, 19 Jun 2019 15:55:03 +0800 From: "Xu, Wei6" To: "Wu, Hao A" , "devel@edk2.groups.io" CC: "Wang, Jian J" , "Zhang, Chao B" Subject: Re: [edk2-devel][Patch v2 7/7] MdeModulePkg: Add Capsule On Disk APIs into CapsuleLib. Thread-Topic: [edk2-devel][Patch v2 7/7] MdeModulePkg: Add Capsule On Disk APIs into CapsuleLib. Thread-Index: AQHVG7VX5pZgR+tGeEiwV1G9b9hRJqaXKVKAgAtZWlA= Date: Wed, 19 Jun 2019 07:55:02 +0000 Message-ID: <59B8EAB3797CDB4091332F0685A110ED50D9746F@SHSMSX104.ccr.corp.intel.com> References: <20190605154203.11012-1-wei6.xu@intel.com> <20190605154203.11012-8-wei6.xu@intel.com> In-Reply-To: Accept-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-originating-ip: [10.239.127.40] MIME-Version: 1.0 Return-Path: wei6.xu@intel.com Content-Language: en-US Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable Thanks a lot for the comments.=20 Please find my answer bellow. > -----Original Message----- > From: Wu, Hao A > Sent: Wednesday, June 12, 2019 3:50 PM > To: devel@edk2.groups.io; Xu, Wei6 > Cc: Wang, Jian J ; Zhang, Chao B > > Subject: RE: [edk2-devel][Patch v2 7/7] MdeModulePkg: Add Capsule On > Disk APIs into CapsuleLib. >=20 > > -----Original Message----- > > From: devel@edk2.groups.io [mailto:devel@edk2.groups.io] On Behalf Of > Xu, > > Wei6 > > Sent: Wednesday, June 05, 2019 11:42 PM > > To: devel@edk2.groups.io > > Cc: Wang, Jian J; Wu, Hao A; Zhang, Chao B; Xu, Wei6 > > Subject: [edk2-devel][Patch v2 7/7] MdeModulePkg: Add Capsule On Disk > > APIs into CapsuleLib. >=20 >=20 > Not directly related with this patch, I saw many function declarations > within .C file for this library. Could you help to propose another serie= s > to add header files to address this (Maybe like the case in > MdeModulePkg/Universal/Variable/RuntimeDxe to handle multi-phases). >=20 Sure, I will work on it after this patch is done. >=20 > Some general level comments: >=20 > I saw some of the new functions whose scope is limited within a single > file have been decorated with keyword 'STATIC'. Could you help to make i= t > consistent for all the newly added global variables/functions? Also, cou= ld > you help to use keyword 'static' (lower case) instead? >=20 I will update all 'STATIC' to 'static'. >=20 > > > > BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3D1852 > > > > CoDCheckCapsuleOnDiskFlag() is to check if CapsuleOnDisk flag in > > "OsIndications" Variable is enabled. It is used to indicate whether > > capsule on disk is provisioned in normal boot path. > > > > CoDClearCapsuleOnDiskFlag() is to to clear CapsuleOnDisk flags, > > including "OsIndications" and "BootNext" variable. > > > > CoDRelocateCapsule() is to relocate the capsules from EFI system > > partition. Depends on PcdCapsuleInRamSupport, there are two solutions > > to relocate the capsule on disk images: > > When Capsule In Ram is supported, the Capsule On Disk images are > > relocated into memory, and call UpdateCapsule() service to deliver > > the capsules. > > When Capsule In Ram is not supported, the Capsule On Disk images are > > relocated into a temp file which will be stored in root directory on > > a platform specific storage device. CapsuleOnDiskLoadPei PEIM will > > retrieve the capsules from the relocation temp file and report > > capsule hobs for them. > > > > CoDRemoveTempFile() is to remove the relocation temp file in the next > > boot after capsules are processed. > > > > Cc: Jian J Wang > > Cc: Hao A Wu > > Cc: Chao B Zhang > > Signed-off-by: Wei6 Xu > > --- > > MdeModulePkg/Include/Library/CapsuleLib.h | 94 +- > > .../Library/DxeCapsuleLibFmp/CapsuleOnDisk.c | 1983 > > ++++++++++++++++++++ > > .../Library/DxeCapsuleLibFmp/CapsuleOnDisk.h | 63 + > > .../Library/DxeCapsuleLibFmp/DxeCapsuleLib.c | 56 +- > > .../Library/DxeCapsuleLibFmp/DxeCapsuleLib.inf | 21 +- > > .../DxeCapsuleLibFmp/DxeCapsuleProcessLib.c | 121 +- > > .../Library/DxeCapsuleLibFmp/DxeCapsuleReportLib.c | 67 +- > > .../DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf | 3 +- > > .../Library/DxeCapsuleLibNull/DxeCapsuleLibNull.c | 85 +- > > 9 files changed, 2466 insertions(+), 27 deletions(-) > > create mode 100644 > > MdeModulePkg/Library/DxeCapsuleLibFmp/CapsuleOnDisk.c > > create mode 100644 > > MdeModulePkg/Library/DxeCapsuleLibFmp/CapsuleOnDisk.h > > > > diff --git a/MdeModulePkg/Include/Library/CapsuleLib.h > > b/MdeModulePkg/Include/Library/CapsuleLib.h > > index 1fc2fba3a2..f3cb17cbf9 100644 > > --- a/MdeModulePkg/Include/Library/CapsuleLib.h > > +++ b/MdeModulePkg/Include/Library/CapsuleLib.h > > @@ -1,17 +1,37 @@ > > /** @file > > > > This library class defines a set of interfaces for how to process c= apsule > > image updates. > > > > -Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved. > > +Copyright (c) 2007 - 2019, Intel Corporation. All rights reserved. > > SPDX-License-Identifier: BSD-2-Clause-Patent > > > > **/ > > > > #ifndef __CAPSULE_LIB_H__ > > #define __CAPSULE_LIB_H__ > > > > +#include > > + > > + > > +typedef struct { > > + // > > + // image address. > > + // > > + VOID *ImageAddress; > > + // > > + // The file info of the image comes from. > > + // if FileInfo =3D=3D NULL. means image does not come from file > > + // > > + EFI_FILE_INFO *FileInfo; > > +} IMAGE_INFO; >=20 >=20 > Will this 'IMAGE_INFO' structure (FileInfo.h include as well) be used by > the consumer of CapsuleLib? For this series, this one is only used withi= n > DxeCapsuleLibFmp (implementation of CapsuleLib). >=20 > If it is only used internally, I suggest to move the definition into > MdeModulePkg\Library\DxeCapsuleLibFmp\CapsuleOnDisk.h. >=20 >=20 > > + > > +// > > +// BOOLEAN Variable to save the total size of all Capsule On Disk dur= ing > > relocation > > +// >=20 >=20 > The above description comment seems not matching the usage of the > variable > perfectly. Looks to me the variable is used to reflect whether the syste= m > is in the capsule on disk state rather than the size information. >=20 >=20 > > +#define COD_RELOCATION_INFO_VAR_NAME L"CodRelocationInfo" > > + > > /** > > The firmware checks whether the capsule image is supported > > by the CapsuleGuid in CapsuleHeader or if there is other specific > > information in > > the capsule image. > > > > @@ -79,6 +99,78 @@ EFI_STATUS > > EFIAPI > > ProcessCapsules ( > > VOID > > ); > > > > +/** > > + This routine is called to check if CapsuleOnDisk flag in OsIndicati= ons > > Variable > > + is enabled. > > + > > + @retval TRUE Flag is enabled > > + @retval FALSE Flag is not enabled > > + > > +**/ > > +BOOLEAN > > +EFIAPI > > +CoDCheckCapsuleOnDiskFlag( > > + VOID > > + ); > > + > > + > > +/** > > + This routine is called to clear CapsuleOnDisk flags including OsInd= ications > > and BootNext variable > > + > > + @retval EFI_SUCCESS All Capsule On Disk flags are cleared > > + > > +**/ > > +EFI_STATUS > > +EFIAPI > > +CoDClearCapsuleOnDiskFlag( > > + VOID > > + ); > > + > > +/** > > + Relocate Capsule on Disk from EFI system partition. > > + > > + Two solution to deliver Capsule On Disk: > > + Solution A: If PcdCapsuleInRamSupport is enabled, relocate Capsule = On > > Disk to memory and call UpdateCapsule(). > > + Solution B: If PcdCapsuleInRamSupport is disabled, relocate Capsule= On > > Disk to a platform-specific NV storage > > + device with BlockIo protocol. > > + > > + Device enumeration like USB costs time, user can input MaxRetry to = tell > > function to retry. > > + Function will stall 100ms between each retry. > > + > > + Side Effects: > > + Capsule Delivery Supported Flag in OsIndication variable and Boot= Next > > variable will be cleared. > > + Solution B: Content corruption. Block IO write directly touches l= ow level > > write. Orignal partitions, file > > + systems of the relocation device will be corrupted. > > + > > + @param[in] MaxRetry Max Connection Retry. Stall 100m= s > between > > each connection try to ensure > > + devices like USB can get enumera= ted. >=20 >=20 > For me, it would be better to explicitly mention the behavior for > 'MaxRetry' with the value 0. Judging from the implementation, 0 means no > retry. >=20 > Similar case for API CoDRemoveTempFile() as well. >=20 > > + > > + @retval EFI_SUCCESS Capsule on Disk images are sucessfully reloca= ted. >=20 >=20 > sucessfully -> successfully > Please help to update this typo in library instances as well. >=20 >=20 > > + > > +**/ > > +EFI_STATUS > > +EFIAPI > > +CoDRelocateCapsule( > > + UINTN MaxRetry > > + ); > > + > > +/** > > + Remove the temp file from the root of EFI System Partition. > > + Device enumeration like USB costs time, user can input MaxRetry to = tell > > function to retry. > > + Function will stall 100ms between each retry. > > + > > + @param[in] MaxRetry Max Connection Retry. Stall 100m= s > between > > each connection try to ensure > > + devices like USB can get enumera= ted. > > + > > + @retval EFI_SUCCESS Remove the temp file successfully. > > + > > +**/ > > +EFI_STATUS > > +EFIAPI > > +CoDRemoveTempFile ( > > + UINTN MaxRetry > > + ); > > + > > #endif > > diff --git a/MdeModulePkg/Library/DxeCapsuleLibFmp/CapsuleOnDisk.c > > b/MdeModulePkg/Library/DxeCapsuleLibFmp/CapsuleOnDisk.c > > new file mode 100644 > > index 0000000000..5f1edbbbae > > --- /dev/null > > +++ b/MdeModulePkg/Library/DxeCapsuleLibFmp/CapsuleOnDisk.c > > @@ -0,0 +1,1983 @@ > > +/** @file > > + The implementation supports Capusle on Disk. > > + > > + Copyright (c) 2019, Intel Corporation. All rights reserved.
> > + SPDX-License-Identifier: BSD-2-Clause-Patent > > + > > +**/ > > + > > +#include "CapsuleOnDisk.h" > > + > > +/** > > + Return if this capsule is a capsule name capsule, based upon > > CapsuleHeader. > > + > > + @param[in] CapsuleHeader A pointer to EFI_CAPSULE_HEADER > > + > > + @retval TRUE It is a capsule name capsule. > > + @retval FALSE It is not a capsule name capsule. > > +**/ > > +BOOLEAN > > +IsCapsuleNameCapsule ( > > + IN EFI_CAPSULE_HEADER *CapsuleHeader > > + ); > > + > > +/** > > + Check the integrity of the capsule name capsule. > > + If the capsule is vaild, return the physical address of each capsul= e name > > string. > > + > > + @param[in] CapsuleHeader Pointer to the capsule header of a caps= ule > > name capsule. > > + @param[out] CapsuleNameNum Number of capsule name. > > + > > + @retval NULL Capsule name capsule is not valid. > > + @retval CapsuleNameBuf Array of capsule name physical address. > > + > > +**/ > > +EFI_PHYSICAL_ADDRESS * > > +ValidateCapsuleNameCapsuleIntegrity ( > > + IN EFI_CAPSULE_HEADER *CapsuleHeader, > > + OUT UINTN *CapsuleNameNum > > + ) > > +{ > > + UINT8 *CapsuleNamePtr; > > + UINT8 *CapsuleNameBufStart; > > + UINT8 *CapsuleNameBufEnd; > > + UINTN Index; > > + UINTN StringSize; > > + EFI_PHYSICAL_ADDRESS *CapsuleNameBuf; > > + > > + if (!IsCapsuleNameCapsule (CapsuleHeader)) { > > + return NULL; > > + } > > + > > + // > > + // Total string size must be even. > > + // > > + if (((CapsuleHeader->CapsuleImageSize - CapsuleHeader->HeaderSize) > & > > BIT0) !=3D 0) { > > + return NULL; > > + } > > + > > + *CapsuleNameNum =3D 0; > > + Index =3D 0; > > + CapsuleNameBufStart =3D (UINT8 *) CapsuleHeader + CapsuleHeader- > > >HeaderSize; > > + > > + // > > + // If strings are not aligned on a 16-bit boundary, reallocate memo= ry for it. > > + // > > + if (((UINTN) CapsuleNameBufStart & BIT0) !=3D 0) { > > + CapsuleNameBufStart =3D AllocateCopyPool (CapsuleHeader- > > >CapsuleImageSize - CapsuleHeader->HeaderSize, CapsuleNameBufStart); > > + } > > + > > + CapsuleNameBufEnd =3D CapsuleNameBufStart + CapsuleHeader- > > >CapsuleImageSize - CapsuleHeader->HeaderSize; > > + > > + CapsuleNamePtr =3D CapsuleNameBufStart; > > + while (CapsuleNamePtr < CapsuleNameBufEnd) { > > + StringSize=3D StrnSizeS ((CHAR16 *) CapsuleNamePtr, > (CapsuleNameBufEnd > > - CapsuleNamePtr)/sizeof(CHAR16)); > > + CapsuleNamePtr +=3D StringSize; > > + (*CapsuleNameNum) ++; > > + } > > + > > + // > > + // Integrity check. > > + // > > + if (CapsuleNamePtr !=3D CapsuleNameBufEnd) { > > + if (CapsuleNameBufStart !=3D (UINT8 *)CapsuleHeader + CapsuleHead= er- > > >HeaderSize) { > > + FreePool (CapsuleNameBufStart); > > + } > > + return NULL; > > + } > > + > > + CapsuleNameBuf =3D AllocatePool (*CapsuleNameNum * sizeof > > (EFI_PHYSICAL_ADDRESS)); > > + if (CapsuleNameBuf =3D=3D NULL) { > > + if (CapsuleNameBufStart !=3D (UINT8 *)CapsuleHeader + CapsuleHead= er- > > >HeaderSize) { > > + FreePool (CapsuleNameBufStart); > > + } > > + return NULL; > > + } > > + > > + CapsuleNamePtr =3D CapsuleNameBufStart; > > + while (CapsuleNamePtr < CapsuleNameBufEnd) { > > + StringSize=3D StrnSizeS ((CHAR16 *) CapsuleNamePtr, > (CapsuleNameBufEnd > > - CapsuleNamePtr)/sizeof(CHAR16)); > > + CapsuleNameBuf[Index] =3D (EFI_PHYSICAL_ADDRESS)(UINTN) > > CapsuleNamePtr; > > + CapsuleNamePtr +=3D StringSize; > > + Index ++; > > + } > > + > > + return CapsuleNameBuf; > > +} > > + > > +/** > > + This routine is called to upper case given unicode string. > > + > > + @param[in] Str String to upper case > > + > > + @retval upper cased string after process > > + > > +**/ > > +STATIC > > +CHAR16 * > > +UpperCaseString ( > > + IN CHAR16 *Str > > + ) > > +{ > > + CHAR16 *Cptr; > > + > > + for (Cptr =3D Str; *Cptr; Cptr++) { > > + if (L'a' <=3D *Cptr && *Cptr <=3D L'z') { > > + *Cptr =3D *Cptr - L'a' + L'A'; > > + } > > + } > > + > > + return Str; > > +} > > + > > +/** > > + This routine is used to return substring before period '.' or '\0' > > + Caller should respsonsible of substr space allocation & free > > + > > + @param[in] Str String to check > > + @param[out] SubStr First part of string before period or= '\0' > > + @param[out] SubStrLen Length of first part of string > > + > > +**/ > > +STATIC > > +VOID > > +GetSubStringBeforePeriod ( > > + IN CHAR16 *Str, > > + OUT CHAR16 *SubStr, > > + OUT UINTN *SubStrLen > > + ) > > +{ > > + UINTN Index; > > + for (Index =3D 0; Str[Index] !=3D L'.' && Str[Index] !=3D L'\0'; In= dex++) { > > + SubStr[Index] =3D Str[Index]; > > + } > > + > > + SubStr[Index] =3D L'\0'; > > + *SubStrLen =3D Index; > > +} > > + > > +/** > > + This routine pad the string in tail with input character. > > + > > + @param[in] StrBuf Str buffer to be padded, should be e= nough > room > > for > > + @param[in] PadLen Expected padding length > > + @param[in] Character Character used to pad > > + > > +**/ > > +STATIC > > +VOID > > +PadStrInTail ( > > + IN CHAR16 *StrBuf, > > + IN UINTN PadLen, > > + IN CHAR16 Character > > + ) > > +{ > > + UINTN Index; > > + > > + for (Index =3D 0; StrBuf[Index] !=3D L'\0'; Index++); > > + > > + while(PadLen !=3D 0) { > > + StrBuf[Index] =3D Character; > > + Index++; > > + PadLen--; > > + } > > + > > + StrBuf[Index] =3D L'\0'; > > +} > > + > > +/** > > + This routine find the offset of the last period '.' of string. If N= o period > exists > > + function FileNameExtension is set to L'\0' > > + > > + @param[in] FileName File name to split between last peri= od > > + @param[out] FileNameFirst First FileName before last period > > + @param[out] FileNameExtension FileName after last period > > + > > +**/ > > +STATIC > > +VOID > > +SplitFileNameExtension ( > > + IN CHAR16 *FileName, > > + OUT CHAR16 *FileNameFirst, > > + OUT CHAR16 *FileNameExtension > > + ) > > +{ > > + UINTN Index; > > + UINTN StringLen; > > + > > + StringLen =3D StrnLenS(FileName, MAX_FILE_NAME_SIZE); > > + for (Index =3D StringLen; Index > 0 && FileName[Index] !=3D L'.'; I= ndex--); > > + > > + // > > + // No period exists. No FileName Extension > > + // > > + if (Index =3D=3D 0 && FileName[Index] !=3D L'.') { > > + FileNameExtension[0] =3D L'\0'; > > + Index =3D StringLen; > > + } else { > > + StrCpyS(FileNameExtension, MAX_FILE_NAME_SIZE, > > &FileName[Index+1]); > > + } > > + > > + // > > + // Copy First file name > > + // > > + StrnCpyS(FileNameFirst, MAX_FILE_NAME_SIZE, FileName, Index); > > + FileNameFirst[Index] =3D L'\0'; > > +} > > + > > +/** > > + This routine is called to get all boot options in the order determn= ined by: > > + 1. "OptionBuf" > > + 2. "BootOrder" > > + > > + @param[out] OptionBuf BootList buffer to all boot options= returned > > + @param[out] OptionCount BootList count of all boot options > returned > > + > > + @retval EFI_SUCCESS There is no error when processing c= apsule > > + > > +**/ > > +EFI_STATUS > > +GetBootOptionInOrder( > > + OUT EFI_BOOT_MANAGER_LOAD_OPTION **OptionBuf, > > + OUT UINTN *OptionCount > > + ) > > +{ > > + EFI_STATUS Status; > > + UINTN DataSize; > > + UINT16 BootNext; > > + CHAR16 BootOptionName[20]; > > + EFI_BOOT_MANAGER_LOAD_OPTION *BootOrderOptionBuf; > > + UINTN BootOrderCount; > > + EFI_BOOT_MANAGER_LOAD_OPTION BootNextOptionEntry; > > + UINTN BootNextCount; > > + EFI_BOOT_MANAGER_LOAD_OPTION *TempBuf; > > + > > + BootOrderOptionBuf =3D NULL; > > + TempBuf =3D NULL; > > + BootNextCount =3D 0; > > + BootOrderCount =3D 0; > > + *OptionBuf =3D NULL; > > + *OptionCount =3D 0; > > + > > + // > > + // First Get BootOption from "BootNext" > > + // > > + DataSize =3D sizeof(BootNext); > > + Status =3D gRT->GetVariable ( > > + EFI_BOOT_NEXT_VARIABLE_NAME, > > + &gEfiGlobalVariableGuid, > > + NULL, > > + &DataSize, > > + (VOID *)&BootNext > > + ); > > + // > > + // BootNext variable is a single UINT16 > > + // > > + if (!EFI_ERROR(Status) && DataSize =3D=3D sizeof(UINT16)) { > > + // > > + // Add the boot next boot option > > + // > > + UnicodeSPrint (BootOptionName, sizeof (BootOptionName), > > L"Boot%04x", BootNext); > > + ZeroMem(&BootNextOptionEntry, > > sizeof(EFI_BOOT_MANAGER_LOAD_OPTION)); > > + Status =3D EfiBootManagerVariableToLoadOption (BootOptionName, > > &BootNextOptionEntry); > > + > > + if (!EFI_ERROR(Status)) { > > + BootNextCount =3D 1; > > + } > > + } > > + > > + // > > + // Second get BootOption from "BootOrder" > > + // > > + BootOrderOptionBuf =3D EfiBootManagerGetLoadOptions > > (&BootOrderCount, LoadOptionTypeBoot); > > + if (BootNextCount =3D=3D 0 && BootOrderCount =3D=3D 0) { > > + return EFI_NOT_FOUND; > > + } > > + > > + // > > + // At least one BootOption is found > > + // > > + TempBuf =3D AllocatePool(sizeof(EFI_BOOT_MANAGER_LOAD_OPTION) * > > (BootNextCount + BootOrderCount)); > > + if (TempBuf !=3D NULL) { > > + if (BootNextCount =3D=3D 1) { > > + CopyMem(TempBuf, &BootNextOptionEntry, > > sizeof(EFI_BOOT_MANAGER_LOAD_OPTION)); > > + } > > + > > + if (BootOrderCount > 0) { > > + CopyMem(TempBuf + BootNextCount, BootOrderOptionBuf, > > sizeof(EFI_BOOT_MANAGER_LOAD_OPTION) * BootOrderCount); > > + } > > + > > + *OptionBuf =3D TempBuf; > > + *OptionCount =3D BootNextCount + BootOrderCount; > > + Status =3D EFI_SUCCESS; > > + } else { > > + Status =3D EFI_OUT_OF_RESOURCES; > > + } > > + > > + FreePool(BootOrderOptionBuf); > > + > > + return Status; > > +} > > + > > +/** > > + This routine is called to get boot option by OptionNumber. > > + > > + @param[in] Number The OptionNumber of boot option > > + @param[out] OptionBuf BootList buffer to all boot options= returned > > + > > + @retval EFI_SUCCESS There is no error when getting boot= option > > + > > +**/ > > +EFI_STATUS > > +GetBootOptionByNumber( > > + IN UINT16 Number, > > + OUT EFI_BOOT_MANAGER_LOAD_OPTION **OptionBuf > > + ) > > +{ > > + EFI_STATUS Status; > > + CHAR16 BootOptionName[20]; > > + EFI_BOOT_MANAGER_LOAD_OPTION BootOption; > > + > > + UnicodeSPrint (BootOptionName, sizeof (BootOptionName), > L"Boot%04x", > > Number); > > + ZeroMem (&BootOption, sizeof (EFI_BOOT_MANAGER_LOAD_OPTION)); > > + Status =3D EfiBootManagerVariableToLoadOption (BootOptionName, > > &BootOption); > > + > > + if (!EFI_ERROR (Status)) { > > + *OptionBuf =3D AllocatePool (sizeof > > (EFI_BOOT_MANAGER_LOAD_OPTION)); > > + CopyMem (*OptionBuf, &BootOption, sizeof > > (EFI_BOOT_MANAGER_LOAD_OPTION)); > > + return EFI_SUCCESS; > > + } > > + > > + return Status; > > +} > > + > > +/** > > + Get Active EFI System Partition within GPT based on device path. > > + > > + @param[in] DevicePath Device path to find a active EFI System Pa= rtition > > + @param[out] FsHandle BootList points to all boot options return= ed > > + > > + @retval EFI_SUCCESS Active EFI System Partition is succesfully= found > > + @retval EFI_NOT_FOUND No Active EFI System Partition is found > > + > > +**/ > > +EFI_STATUS > > +GetEfiSysPartitionFromDevPath( > > + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, > > + OUT EFI_HANDLE *FsHandle > > + ) > > +{ > > + EFI_STATUS Status; > > + EFI_DEVICE_PATH_PROTOCOL *TempDevicePath; > > + HARDDRIVE_DEVICE_PATH *Hd; > > + EFI_HANDLE Handle; > > + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Fs; > > + > > + // > > + // Check if the device path contains GPT node > > + // > > + TempDevicePath =3D DevicePath; > > + while (!IsDevicePathEnd (TempDevicePath)) { > > + if ((DevicePathType (TempDevicePath) =3D=3D MEDIA_DEVICE_PATH) && > > + (DevicePathSubType (TempDevicePath) =3D=3D MEDIA_HARDDRIVE_DP)= ) > { > > + Hd =3D (HARDDRIVE_DEVICE_PATH *)TempDevicePath; > > + if (Hd->MBRType =3D=3D MBR_TYPE_EFI_PARTITION_TABLE_HEADER) { > > + break; > > + } > > + } > > + TempDevicePath =3D NextDevicePathNode (TempDevicePath); > > + } > > + > > + if (!IsDevicePathEnd (TempDevicePath)) { > > + // > > + // Search for EFI system partition protocol on full device path i= n Boot > > Option > > + // > > + Status =3D gBS->LocateDevicePath (&gEfiPartTypeSystemPartGuid, > > &DevicePath, &Handle); > > + > > + // > > + // Search for simple file system on this handler > > + // > > + if (!EFI_ERROR(Status)) { > > + Status =3D gBS->HandleProtocol(Handle, > > &gEfiSimpleFileSystemProtocolGuid, (VOID **)&Fs); > > + if (!EFI_ERROR(Status)) { > > + *FsHandle =3D Handle; > > + return EFI_SUCCESS; > > + } > > + } > > + } > > + > > + return EFI_NOT_FOUND; > > +} > > + > > +/** > > + This routine is called to get Simple File System protocol on the fi= rst EFI > > system partition found in > > + active boot option. The boot option list is detemined in order by > > + 1. "BootNext" > > + 2. "BootOrder" > > + > > + @param[in] MaxRetry Max Connection Retry. Stall 100= ms > between > > each connection try to ensure > > + device like USB can get enumera= ted. > > + @param[in, out] LoadOptionNumber On input, specify the boot opti= on > to > > get EFI system partition. > > + On output, return the OptionNum= ber of the boot > option > > where EFI > > + system partition is got from. > > + @param[out] FsFsHandle Simple File System Protocol fou= nd on > first > > active EFI system partition > > + > > + @retval EFI_SUCCESS Simple File System protocol found for EFI s= ystem > > partition > > + @retval EFI_NOT_FOUND No Simple File System protocol found for EF= I > > system partition > > + > > +**/ > > +EFI_STATUS > > +GetEfiSysPartitionFromActiveBootOption( > > + IN UINTN MaxRetry, > > + IN OUT UINT16 **LoadOptionNumber, > > + OUT EFI_HANDLE *FsHandle > > + ) > > +{ > > + EFI_STATUS Status; > > + EFI_BOOT_MANAGER_LOAD_OPTION *BootOptionBuf; > > + UINTN BootOptionNum; > > + UINTN Index; > > + EFI_DEVICE_PATH_PROTOCOL *DevicePath; > > + EFI_DEVICE_PATH_PROTOCOL *CurFullPath; > > + EFI_DEVICE_PATH_PROTOCOL *PreFullPath; > > + > > + *FsHandle =3D NULL; > > + > > + if (*LoadOptionNumber !=3D NULL) { > > + BootOptionNum =3D 1; > > + Status =3D GetBootOptionByNumber(**LoadOptionNumber, > > &BootOptionBuf); > > + if (EFI_ERROR(Status)) { > > + DEBUG ((DEBUG_ERROR, "GetBootOptionByIndex Failed %x! No > > BootOption available for connection\n", Status)); > > + return Status; > > + } > > + } else { > > + Status =3D GetBootOptionInOrder(&BootOptionBuf, &BootOptionNum); > > + if (EFI_ERROR(Status)) { > > + DEBUG ((DEBUG_ERROR, "GetBootOptionInOrder Failed %x! No > > BootOption available for connection\n", Status)); > > + return Status; > > + } > > + } > > + > > + // > > + // Search BootOptionList to check if it is an active boot option wi= th EFI > > system partition > > + // 1. Connect device path > > + // 2. expend short/plug in devicepath > > + // 3. LoadImage > > + // > > + for (Index =3D 0; Index < BootOptionNum; Index++) { > > + // > > + // Get the boot option from the link list > > + // > > + DevicePath =3D BootOptionBuf[Index].FilePath; > > + > > + // > > + // Skip inactive or legacy boot options > > + // > > + if ((BootOptionBuf[Index].Attributes & LOAD_OPTION_ACTIVE) =3D=3D= 0 || > > + DevicePathType (DevicePath) =3D=3D BBS_DEVICE_PATH) { > > + continue; > > + } > > + > > + DEBUG_CODE ( > > + CHAR16 *DevicePathStr; > > + > > + DevicePathStr =3D ConvertDevicePathToText(DevicePath, TRUE, TRU= E); > > + if (DevicePathStr !=3D NULL){ > > + DEBUG((DEBUG_INFO, "Try BootOption %s\n", DevicePathStr)); > > + FreePool(DevicePathStr); > > + } else { > > + DEBUG((DEBUG_INFO, "DevicePathToStr failed\n")); > > + } > > + ); > > + > > + CurFullPath =3D NULL; > > + // > > + // Try every full device Path generated from bootoption > > + // > > + do { > > + PreFullPath =3D CurFullPath; > > + CurFullPath =3D > > EfiBootManagerGetNextLoadOptionDevicePath(DevicePath, CurFullPath); > > + > > + if (PreFullPath !=3D NULL) { > > + FreePool (PreFullPath); > > + } > > + > > + if (CurFullPath =3D=3D NULL) { > > + // > > + // No Active EFI system partition is found in BootOption devi= ce path > > + // > > + Status =3D EFI_NOT_FOUND; > > + break; > > + } > > + > > + DEBUG_CODE ( > > + CHAR16 *DevicePathStr1; > > + > > + DevicePathStr1 =3D ConvertDevicePathToText(CurFullPath, TRUE,= TRUE); > > + if (DevicePathStr1 !=3D NULL){ > > + DEBUG((DEBUG_INFO, "Full device path %s\n", DevicePathStr1)= ); > > + FreePool(DevicePathStr1); > > + } > > + ); > > + > > + // > > + // Make sure the boot option device path connected. > > + // Only handle first device in boot option. Other optional devi= ce paths > > are described as OSV specific > > + // FullDevice could contain extra directory & file info. So don= 't check > > connection status here. > > + // > > + EfiBootManagerConnectDevicePath (CurFullPath, NULL); > > + Status =3D GetEfiSysPartitionFromDevPath(CurFullPath, FsHandle)= ; > > + > > + // > > + // Some relocation device like USB need more time to get enumer= ated > > + // > > + while (EFI_ERROR(Status) && MaxRetry > 0) { > > + EfiBootManagerConnectDevicePath(CurFullPath, NULL); > > + > > + // > > + // Search for EFI system partition protocol on full device pa= th in Boot > > Option > > + // > > + Status =3D GetEfiSysPartitionFromDevPath(CurFullPath, FsHandl= e); > > + if (!EFI_ERROR(Status)) { > > + break; > > + } > > + DEBUG((DEBUG_ERROR, "GetEfiSysPartitionFromDevPath > Loop %x\n", > > Status)); > > + // > > + // Stall 100ms if connection failed to ensure USB stack is re= ady > > + // > > + gBS->Stall(100000); > > + MaxRetry --; > > + } > > + } while(EFI_ERROR(Status)); > > + > > + // > > + // Find a qualified Simple File System > > + // > > + if (!EFI_ERROR(Status)) { > > + break; > > + } > > + > > + } > > + > > + // > > + // Return the OptionNumber of the boot option where EFI system > > partition is got from > > + // > > + if (*LoadOptionNumber =3D=3D NULL) { > > + *LoadOptionNumber =3D AllocateCopyPool (sizeof(UINT16), (UINT16 *= ) > > &BootOptionBuf[Index].OptionNumber); > > + } > > + > > + // > > + // No qualified EFI system partition found > > + // > > + if (*FsHandle =3D=3D NULL) { > > + Status =3D EFI_NOT_FOUND; > > + } > > + > > + DEBUG_CODE ( > > + CHAR16 *DevicePathStr2; > > + if (*FsHandle !=3D NULL) { > > + DevicePathStr2 =3D ConvertDevicePathToText(CurFullPath, TRUE, T= RUE); > > + if (DevicePathStr2 !=3D NULL){ > > + DEBUG((DEBUG_INFO, "Found Active EFI System Partion on %s\n", > > DevicePathStr2)); > > + FreePool(DevicePathStr2); > > + } > > + } else { > > + DEBUG((DEBUG_INFO, "Failed to found Active EFI System Partion\n= ")); > > + } > > + ); > > + > > + if (CurFullPath !=3D NULL) { > > + FreePool(CurFullPath); > > + } > > + > > + // > > + // Free BootOption Buffer > > + // > > + for (Index =3D 0; Index < BootOptionNum; Index++) { > > + if (BootOptionBuf[Index].Description !=3D NULL) { > > + FreePool(BootOptionBuf[Index].Description); > > + } > > + > > + if (BootOptionBuf[Index].FilePath !=3D NULL) { > > + FreePool(BootOptionBuf[Index].FilePath); > > + } > > + > > + if (BootOptionBuf[Index].OptionalData !=3D NULL) { > > + FreePool(BootOptionBuf[Index].OptionalData); > > + } > > + } > > + > > + FreePool(BootOptionBuf); > > + > > + return Status; > > +} > > + > > + > > +/** > > + This routine is called to get all file infos with in a given dir & = with given file > > attribute, the file info is listed in > > + alphabetical order described in UEFI spec. > > + > > + @param[in] Dir Directory file handler > > + @param[in] FileAttr Attribute of file to be red from di= rectory > > + @param[out] FileInfoList File images info list red from dire= ctory > > + @param[out] FileNum File images number red from directo= ry > > + > > + @retval EFI_SUCCESS File FileInfo list in the given > > + > > +**/ > > +EFI_STATUS > > +GetFileInfoListInAlphabetFromDir( > > + IN EFI_FILE_HANDLE Dir, > > + IN UINT64 FileAttr, > > + OUT LIST_ENTRY *FileInfoList, > > + OUT UINTN *FileNum > > + ) > > +{ > > + EFI_STATUS Status; > > + FILE_INFO_ENTRY *NewFileInfoEntry; > > + FILE_INFO_ENTRY *TempFileInfoEntry; > > + EFI_FILE_INFO *FileInfo; > > + CHAR16 *NewFileName; > > + CHAR16 *ListedFileName; > > + CHAR16 *NewFileNameExtension; > > + CHAR16 *ListedFileNameExtension; > > + CHAR16 *TempNewSubStr; > > + CHAR16 *TempListedSubStr; > > + LIST_ENTRY *Link; > > + BOOLEAN NoFile; > > + UINTN FileCount; > > + UINTN IndexNew; > > + UINTN IndexListed; > > + UINTN NewSubStrLen; > > + UINTN ListedSubStrLen; > > + INTN SubStrCmpResult; > > + > > + Status =3D EFI_SUCCESS; > > + NewFileName =3D NULL; > > + ListedFileName =3D NULL; > > + NewFileNameExtension =3D NULL; > > + ListedFileNameExtension =3D NULL; > > + TempNewSubStr =3D NULL; > > + TempListedSubStr =3D NULL; > > + NoFile =3D FALSE; > > + FileCount =3D 0; > > + > > + InitializeListHead(FileInfoList); > > + > > + TempNewSubStr =3D (CHAR16 *) > > AllocateZeroPool(MAX_FILE_NAME_SIZE); > > + TempListedSubStr =3D (CHAR16 *) > > AllocateZeroPool(MAX_FILE_NAME_SIZE); > > + > > + if (TempNewSubStr =3D=3D NULL || TempListedSubStr =3D=3D NULL ) { > > + Status =3D EFI_OUT_OF_RESOURCES; > > + goto EXIT; > > + } > > + > > + for ( Status =3D FileHandleFindFirstFile(Dir, &FileInfo) > > + ; !EFI_ERROR(Status) && !NoFile > > + ; Status =3D FileHandleFindNextFile(Dir, FileInfo, &NoFile) > > + ){ > > + > > + // > > + // Skip file with mismatching File attribute > > + // > > + if ((FileInfo->Attribute & (FileAttr)) =3D=3D 0) { > > + continue; > > + } > > + > > + NewFileInfoEntry =3D NULL; > > + NewFileInfoEntry =3D > > (FILE_INFO_ENTRY*)AllocateZeroPool(sizeof(FILE_INFO_ENTRY)); > > + if (NewFileInfoEntry =3D=3D NULL) { > > + Status =3D EFI_OUT_OF_RESOURCES; > > + goto EXIT; > > + } > > + NewFileInfoEntry->Signature =3D FILE_INFO_SIGNATURE; > > + NewFileInfoEntry->FileInfo =3D AllocateCopyPool((UINTN) FileInfo= ->Size, > > FileInfo); > > + if (NewFileInfoEntry->FileInfo =3D=3D NULL) { > > + FreePool(NewFileInfoEntry); > > + Status =3D EFI_OUT_OF_RESOURCES; > > + goto EXIT; > > + } > > + > > + NewFileInfoEntry->FileNameFirstPart =3D (CHAR16 *) > > AllocateZeroPool(MAX_FILE_NAME_SIZE); > > + if (NewFileInfoEntry->FileNameFirstPart =3D=3D NULL) { > > + FreePool(NewFileInfoEntry->FileInfo); > > + FreePool(NewFileInfoEntry); > > + Status =3D EFI_OUT_OF_RESOURCES; > > + goto EXIT; > > + } > > + NewFileInfoEntry->FileNameSecondPart =3D (CHAR16 *) > > AllocateZeroPool(MAX_FILE_NAME_SIZE); > > + if (NewFileInfoEntry->FileNameSecondPart =3D=3D NULL) { > > + FreePool(NewFileInfoEntry->FileInfo); > > + FreePool(NewFileInfoEntry->FileNameFirstPart); > > + FreePool(NewFileInfoEntry); > > + Status =3D EFI_OUT_OF_RESOURCES; > > + goto EXIT; > > + } > > + > > + // > > + // Splitter the whole New file name into 2 parts between the last= period > > L'.' into NewFileName NewFileExtension > > + // If no period in the whole file name. NewFileExtension is set t= o L'\0' > > + // > > + NewFileName =3D NewFileInfoEntry->FileNameFirstPart; > > + NewFileNameExtension =3D NewFileInfoEntry->FileNameSecondPart; > > + SplitFileNameExtension(FileInfo->FileName, NewFileName, > > NewFileNameExtension); > > + UpperCaseString(NewFileName); > > + UpperCaseString(NewFileNameExtension); > > + > > + // > > + // Insert capsule file in alphabetical ordered list > > + // > > + for (Link =3D FileInfoList->ForwardLink; Link !=3D FileInfoList; = Link =3D Link- > > >ForwardLink) { > > + // > > + // Get the FileInfo from the link list > > + // > > + TempFileInfoEntry =3D CR (Link, FILE_INFO_ENTRY, Link, > > FILE_INFO_SIGNATURE); > > + ListedFileName =3D TempFileInfoEntry->FileNameFirstPar= t; > > + ListedFileNameExtension =3D TempFileInfoEntry->FileNameSecondPa= rt; > > + > > + // > > + // Follow rule in UEFI spec 8.5.5 to compare file name > > + // > > + IndexListed =3D 0; > > + IndexNew =3D 0; > > + while (TRUE){ > > + // > > + // First compare each substrings in NewFileName & ListedFileN= ame > > between periods > > + // > > + GetSubStringBeforePeriod(&NewFileName[IndexNew], > > TempNewSubStr, &NewSubStrLen); > > + GetSubStringBeforePeriod(&ListedFileName[IndexListed], > > TempListedSubStr, &ListedSubStrLen); > > + if (NewSubStrLen > ListedSubStrLen) { > > + // > > + // Substr in NewFileName is longer. Pad tail with SPACE > > + // > > + PadStrInTail(TempListedSubStr, NewSubStrLen - ListedSubStrL= en, L' > '); > > + } else if (NewSubStrLen < ListedSubStrLen){ > > + // > > + // Substr in ListedFileName is longer. Pad tail with SPACE > > + // > > + PadStrInTail(TempNewSubStr, ListedSubStrLen - NewSubStrLen,= L' '); > > + } > > + > > + SubStrCmpResult =3D StrnCmp(TempNewSubStr, TempListedSubStr, > > MAX_FILE_NAME_LEN); > > + if (SubStrCmpResult !=3D 0) { > > + break; > > + } > > + > > + // > > + // Move to skip this substring > > + // > > + IndexNew +=3D NewSubStrLen; > > + IndexListed +=3D ListedSubStrLen; > > + // > > + // Reach File First Name end > > + // > > + if (NewFileName[IndexNew] =3D=3D L'\0' || ListedFileName[Inde= xListed] > =3D=3D > > L'\0') { > > + break; > > + } > > + > > + // > > + // Skip the period L'.' > > + // > > + IndexNew++; > > + IndexListed++; > > + } > > + > > + if (SubStrCmpResult < 0) { > > + // > > + // NewFileName is smaller. Find the right place to insert New= file > > + // > > + break; > > + } else if (SubStrCmpResult =3D=3D 0) { > > + // > > + // 2 cases whole NewFileName is smaller than ListedFileName > > + // 1. if NewFileName =3D=3D ListedFileName. Continue to com= pare > > FileNameExtension > > + // 2. if NewFileName is shorter than ListedFileName > > + // > > + if (NewFileName[IndexNew] =3D=3D L'\0') { > > + if (ListedFileName[IndexListed] !=3D L'\0' || > > (StrnCmp(NewFileNameExtension, ListedFileNameExtension, > > MAX_FILE_NAME_LEN) < 0)) { > > + break; > > + } > > + } > > + } > > + > > + // > > + // Other case, ListedFileName is smaller. Continue to compare t= he next > > file in the list > > + // > > + } > > + > > + // > > + // If Find an entry in the list whose name is bigger than new Fil= eInfo in > > alphabet order > > + // Insert it before this entry > > + // else > > + // Insert at the tail of this list (Link =3D FileInfoList) > > + // > > + InsertTailList(Link, &NewFileInfoEntry->Link); > > + > > + FileCount++; > > + } > > + > > + *FileNum =3D FileCount; > > + > > +EXIT: > > + > > + if (TempNewSubStr !=3D NULL) { > > + FreePool(TempNewSubStr); > > + } > > + > > + if (TempListedSubStr !=3D NULL) { > > + FreePool(TempListedSubStr); > > + } > > + > > + if (EFI_ERROR(Status)) { > > + while(!IsListEmpty(FileInfoList)) { > > + Link =3D FileInfoList->ForwardLink; > > + RemoveEntryList(Link); > > + > > + TempFileInfoEntry =3D CR (Link, FILE_INFO_ENTRY, Link, > > FILE_INFO_SIGNATURE); > > + > > + FreePool(TempFileInfoEntry->FileInfo); > > + FreePool(TempFileInfoEntry->FileNameFirstPart); > > + FreePool(TempFileInfoEntry->FileNameSecondPart); > > + FreePool(TempFileInfoEntry); > > + } > > + *FileNum =3D 0; > > + } > > + > > + return Status; > > +} > > + > > + > > +/** > > + This routine is called to get all qualified image from file from an= given > > directory > > + in alphabetic order. All the file image is copied to allocated boot= time > > memory. > > + Caller should free these memory > > + > > + @param[in] Dir Directory file handler > > + @param[in] FileAttr Attribute of file to be red from directo= ry > > + @param[out] FilePtr File images Info buffer red from directo= ry > > + @param[out] FileNum File images number red from directory > > + > > + @retval EFI_SUCCESS Succeed to get all capsules in alphabetic orde= r. > > + > > +**/ > > +EFI_STATUS > > +GetFileImageInAlphabetFromDir( > > + IN EFI_FILE_HANDLE Dir, > > + IN UINT64 FileAttr, > > + OUT IMAGE_INFO **FilePtr, > > + OUT UINTN *FileNum > > + ) > > +{ > > + EFI_STATUS Status; > > + LIST_ENTRY *Link; > > + EFI_FILE_HANDLE FileHandle; > > + FILE_INFO_ENTRY *FileInfoEntry; > > + EFI_FILE_INFO *FileInfo; > > + UINTN FileCount; > > + IMAGE_INFO *TempFilePtrBuf; > > + UINTN Size; > > + LIST_ENTRY FileInfoList; > > + > > + FileHandle =3D NULL; > > + FileCount =3D 0; > > + TempFilePtrBuf =3D NULL; > > + *FilePtr =3D NULL; > > + > > + // > > + // Get file list in Dir in alphabetical order > > + // > > + Status =3D GetFileInfoListInAlphabetFromDir( > > + Dir, > > + FileAttr, > > + &FileInfoList, > > + &FileCount > > + ); > > + if (EFI_ERROR(Status)) { > > + DEBUG ((DEBUG_ERROR, "GetFileInfoListInAlphabetFromDir > Failed!\n")); > > + goto EXIT; > > + } > > + > > + if (FileCount =3D=3D 0) { > > + DEBUG ((DEBUG_ERROR, "No file found in Dir!\n")); > > + Status =3D EFI_NOT_FOUND; > > + goto EXIT; > > + } > > + > > + TempFilePtrBuf =3D (IMAGE_INFO *)AllocateZeroPool(sizeof(IMAGE_INFO= ) > > * FileCount); > > + if (TempFilePtrBuf =3D=3D NULL) { > > + Status =3D EFI_OUT_OF_RESOURCES; > > + goto EXIT; > > + } > > + > > + // > > + // Read all files from FileInfoList to BS memory > > + // > > + FileCount =3D 0; > > + for (Link =3D FileInfoList.ForwardLink; Link !=3D &FileInfoList; Li= nk =3D Link- > > >ForwardLink) { > > + // > > + // Get FileInfo from the link list > > + // > > + FileInfoEntry =3D CR (Link, FILE_INFO_ENTRY, Link, > FILE_INFO_SIGNATURE); > > + FileInfo =3D FileInfoEntry->FileInfo; > > + > > + Status =3D Dir->Open( > > + Dir, > > + &FileHandle, > > + FileInfo->FileName, > > + EFI_FILE_MODE_READ, > > + 0 > > + ); > > + if (EFI_ERROR(Status)){ > > + continue; > > + } > > + > > + Size =3D (UINTN)FileInfo->FileSize; > > + TempFilePtrBuf[FileCount].ImageAddress =3D AllocateZeroPool(Size)= ; > > + if (TempFilePtrBuf[FileCount].ImageAddress =3D=3D NULL) { > > + DEBUG((DEBUG_ERROR, "Fail to allocate memory for capsule. Stop > > processing the rest.\n")); > > + break; > > + } > > + > > + Status =3D FileHandle->Read( > > + FileHandle, > > + &Size, > > + TempFilePtrBuf[FileCount].ImageAddress > > + ); > > + > > + FileHandle->Close(FileHandle); > > + > > + // > > + // Skip read error file > > + // > > + if (EFI_ERROR(Status) || Size !=3D (UINTN)FileInfo->FileSize) { > > + // > > + // Remove this error file info accordingly > > + // & move Link to BackLink > > + // > > + Link =3D RemoveEntryList(Link); > > + Link =3D Link->BackLink; > > + > > + FreePool(FileInfoEntry->FileInfo); > > + FreePool(FileInfoEntry->FileNameFirstPart); > > + FreePool(FileInfoEntry->FileNameSecondPart); > > + FreePool(FileInfoEntry); > > + > > + FreePool(TempFilePtrBuf[FileCount].ImageAddress); > > + TempFilePtrBuf[FileCount].ImageAddress =3D NULL; > > + TempFilePtrBuf[FileCount].FileInfo =3D NULL; > > + > > + continue; > > + } > > + TempFilePtrBuf[FileCount].FileInfo =3D FileInfo; > > + FileCount++; > > + } > > + > > + DEBUG_CODE ( > > + for (Link =3D FileInfoList.ForwardLink; Link !=3D &FileInfoList; = Link =3D Link- > > >ForwardLink) { > > + FileInfoEntry =3D CR (Link, FILE_INFO_ENTRY, Link, > FILE_INFO_SIGNATURE); > > + FileInfo =3D FileInfoEntry->FileInfo; > > + DEBUG((DEBUG_INFO, "Successfully read capsule file %s from disk= .\n", > > FileInfo->FileName)); > > + } > > + ); > > + > > +EXIT: > > + > > + *FilePtr =3D TempFilePtrBuf; > > + *FileNum =3D FileCount; > > + > > + // > > + // FileInfo will be freed by Calller > > + // > > + while(!IsListEmpty(&FileInfoList)) { > > + Link =3D FileInfoList.ForwardLink; > > + RemoveEntryList(Link); > > + > > + FileInfoEntry =3D CR (Link, FILE_INFO_ENTRY, Link, > FILE_INFO_SIGNATURE); > > + > > + FreePool(FileInfoEntry->FileNameFirstPart); > > + FreePool(FileInfoEntry->FileNameSecondPart); > > + FreePool(FileInfoEntry); > > + } > > + > > + return Status; > > +} > > + > > +/** > > + This routine is called to remove all qualified image from file from= an given > > directory. > > + > > + @param[in] Dir Directory file handler > > + @param[in] FileAttr Attribute of files to be deleted > > + > > + @retval EFI_SUCCESS Succeed to remove all files from an given dire= ctory. > > + > > +**/ > > +EFI_STATUS > > +RemoveFileFromDir( > > + IN EFI_FILE_HANDLE Dir, > > + IN UINT64 FileAttr > > + ) > > +{ > > + EFI_STATUS Status; > > + LIST_ENTRY *Link; > > + LIST_ENTRY FileInfoList; > > + EFI_FILE_HANDLE FileHandle; > > + FILE_INFO_ENTRY *FileInfoEntry; > > + EFI_FILE_INFO *FileInfo; > > + UINTN FileCount; > > + > > + FileHandle =3D NULL; > > + > > + // > > + // Get file list in Dir in alphabetical order > > + // > > + Status =3D GetFileInfoListInAlphabetFromDir( > > + Dir, > > + FileAttr, > > + &FileInfoList, > > + &FileCount > > + ); > > + if (EFI_ERROR(Status)) { > > + DEBUG ((DEBUG_ERROR, "GetFileInfoListInAlphabetFromDir > Failed!\n")); > > + goto EXIT; > > + } > > + > > + if (FileCount =3D=3D 0) { > > + DEBUG ((DEBUG_ERROR, "No file found in Dir!\n")); > > + Status =3D EFI_NOT_FOUND; > > + goto EXIT; > > + } > > + > > + // > > + // Delete all files with given attribute in Dir > > + // > > + for (Link =3D FileInfoList.ForwardLink; Link !=3D &(FileInfoList); = Link =3D Link- > > >ForwardLink) { > > + // > > + // Get FileInfo from the link list > > + // > > + FileInfoEntry =3D CR (Link, FILE_INFO_ENTRY, Link, > FILE_INFO_SIGNATURE); > > + FileInfo =3D FileInfoEntry->FileInfo; > > + > > + Status =3D Dir->Open( > > + Dir, > > + &FileHandle, > > + FileInfo->FileName, > > + EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE, > > + 0 > > + ); > > + if (EFI_ERROR(Status)){ > > + continue; > > + } > > + > > + Status =3D FileHandle->Delete(FileHandle); > > + } > > + > > +EXIT: > > + > > + while(!IsListEmpty(&FileInfoList)) { > > + Link =3D FileInfoList.ForwardLink; > > + RemoveEntryList(Link); > > + > > + FileInfoEntry =3D CR (Link, FILE_INFO_ENTRY, Link, > FILE_INFO_SIGNATURE); > > + > > + FreePool(FileInfoEntry->FileInfo); > > + FreePool(FileInfoEntry); > > + } > > + > > + return Status; > > +} > > + > > +/** > > + This routine is called to get all caspules from file. The capsule f= ile image is > > + copied to BS memory. Caller is responsible to free them. > > + > > + @param[in] MaxRetry Max Connection Retry. Stall 100m= s > between > > each connection try to ensure > > + devices like USB can get enumera= ted. > > + @param[out] CapsulePtr Copied Capsule file Image Info b= uffer > > + @param[out] CapsuleNum CapsuleNumber > > + @param[out] FsHandle File system handle > > + @param[out] LoadOptionNumber OptionNumber of boot option > > + > > + @retval EFI_SUCCESS Succeed to get all capsules. > > + > > +**/ > > +EFI_STATUS > > +EFIAPI >=20 >=20 > Please help to remove the keyword 'EFIAPI' for internal function. >=20 >=20 > > +GetAllCapsuleOnDisk( > > + IN UINTN MaxRetry, > > + OUT IMAGE_INFO **CapsulePtr, > > + OUT UINTN *CapsuleNum, > > + OUT EFI_HANDLE *FsHandle, > > + OUT UINT16 *LoadOptionNumber > > + ) > > +{ > > + EFI_STATUS Status; > > + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Fs; > > + EFI_FILE_HANDLE RootDir; > > + EFI_FILE_HANDLE FileDir; > > + UINT16 *TempOptionNumber; > > + > > + Fs =3D NULL; > > + RootDir =3D NULL; > > + FileDir =3D NULL; > > + TempOptionNumber =3D NULL; > > + *CapsuleNum =3D 0; > > + > > + Status =3D GetEfiSysPartitionFromActiveBootOption(MaxRetry, > > &TempOptionNumber, FsHandle); > > + if (EFI_ERROR(Status)) { > > + return Status; > > + } > > + > > + Status =3D gBS->HandleProtocol(*FsHandle, > > &gEfiSimpleFileSystemProtocolGuid, (VOID **)&Fs); > > + if (EFI_ERROR(Status)) { > > + return Status; > > + } > > + > > + Status =3D Fs->OpenVolume(Fs, &RootDir); > > + if (EFI_ERROR(Status)) { > > + return Status; > > + } > > + > > + Status =3D RootDir->Open( > > + RootDir, > > + &FileDir, > > + EFI_CAPSULE_FILE_DIRECTORY, > > + EFI_FILE_MODE_READ, > > + 0 > > + ); > > + if (EFI_ERROR(Status)) { > > + DEBUG((DEBUG_ERROR, "CodLibGetAllCapsuleOnDisk fail to open > > RootDir!\n")); > > + goto EXIT; > > + } > > + > > + // > > + // Only Load files with EFI_FILE_SYSTEM or EFI_FILE_ARCHIVE attribu= te > > + // ignore EFI_FILE_READ_ONLY, EFI_FILE_HIDDEN, EFI_FILE_RESERVED, > > EFI_FILE_DIRECTORY > > + // > > + Status =3D GetFileImageInAlphabetFromDir( > > + FileDir, > > + EFI_FILE_SYSTEM | EFI_FILE_ARCHIVE, > > + CapsulePtr, > > + CapsuleNum > > + ); > > + DEBUG((DEBUG_INFO, "GetFileImageInAlphabetFromDir status %x\n", > > Status)); > > + > > + // > > + // Always remove file to avoid deadloop in capsule process > > + // > > + Status =3D RemoveFileFromDir(FileDir, EFI_FILE_SYSTEM | > > EFI_FILE_ARCHIVE); > > + DEBUG((DEBUG_INFO, "RemoveFileFromDir status %x\n", Status)); > > + > > + if (LoadOptionNumber !=3D NULL) { > > + *LoadOptionNumber =3D *TempOptionNumber; > > + } > > + > > +EXIT: > > + > > + if (FileDir !=3D NULL) { > > + FileDir->Close (FileDir); > > + } > > + > > + if (RootDir !=3D NULL) { > > + RootDir->Close (RootDir); > > + } > > + > > + return Status; > > +} > > + > > +/** > > + Build Gather list for a list of capsule images. > > + > > + @param[in] CapsuleBuffer An array of pointer to capsule images > > + @param[in] CapsuleSize An array of UINTN to capsule images si= ze > > + @param[in] CapsuleNum The count of capsule images > > + @param[out] BlockDescriptors The block descriptors for the capsule > > images > > + > > + @retval EFI_SUCCESS The block descriptors for the capsule images ar= e > > constructed. > > + > > +**/ > > +EFI_STATUS > > +BuildGatherList ( > > + IN VOID **CapsuleBuffer, > > + IN UINTN *CapsuleSize, > > + IN UINTN CapsuleNum, > > + OUT EFI_CAPSULE_BLOCK_DESCRIPTOR **BlockDescriptors > > + ) > > +{ > > + EFI_STATUS Status; > > + EFI_CAPSULE_BLOCK_DESCRIPTOR *BlockDescriptors1; > > + EFI_CAPSULE_BLOCK_DESCRIPTOR *BlockDescriptorPre; > > + EFI_CAPSULE_BLOCK_DESCRIPTOR *BlockDescriptorsHeader; > > + UINTN Index; > > + > > + BlockDescriptors1 =3D NULL; > > + BlockDescriptorPre =3D NULL; > > + BlockDescriptorsHeader =3D NULL; > > + > > + for (Index =3D 0; Index < CapsuleNum; Index++) { > > + // > > + // Allocate memory for the descriptors. > > + // > > + BlockDescriptors1 =3D AllocateZeroPool (2 * sizeof > > (EFI_CAPSULE_BLOCK_DESCRIPTOR)); > > + if (BlockDescriptors1 =3D=3D NULL) { > > + DEBUG ((DEBUG_ERROR, "BuildGatherList: failed to allocate memor= y > for > > descriptors\n")); > > + Status =3D EFI_OUT_OF_RESOURCES; > > + goto ERREXIT; > > + } else { > > + DEBUG ((DEBUG_INFO, "BuildGatherList: creating capsule descript= ors > at > > 0x%X\n", (UINTN) BlockDescriptors1)); > > + } > > + > > + // > > + // Record descirptor header > > + // > > + if (Index =3D=3D 0) { > > + BlockDescriptorsHeader =3D BlockDescriptors1; > > + } > > + > > + if (BlockDescriptorPre !=3D NULL) { > > + BlockDescriptorPre->Union.ContinuationPointer =3D (UINTN) > > BlockDescriptors1; > > + BlockDescriptorPre->Length =3D 0; > > + } > > + > > + BlockDescriptors1->Union.DataBlock =3D (UINTN) CapsuleBuffer[Inde= x]; > > + BlockDescriptors1->Length =3D CapsuleSize[Index]; > > + > > + BlockDescriptorPre =3D BlockDescriptors1 + 1; > > + BlockDescriptors1 =3D NULL; > > + } > > + > > + // > > + // Null-terminate. > > + // > > + if (BlockDescriptorPre !=3D NULL) { > > + BlockDescriptorPre->Union.ContinuationPointer =3D (UINTN)NULL; > > + BlockDescriptorPre->Length =3D 0; > > + *BlockDescriptors =3D BlockDescriptorsHeader; > > + } > > + > > + return EFI_SUCCESS; > > + > > +ERREXIT: > > + if (BlockDescriptors1 !=3D NULL) { > > + FreePool (BlockDescriptors1); > > + } > > + > > + return Status; > > +} > > + > > +/** > > + This routine is called to check if CapsuleOnDisk flag in OsIndicati= ons > > Variable > > + is enabled. > > + > > + @retval TRUE Flag is enabled > > + @retval FALSE Flag is not enabled > > + > > +**/ > > +BOOLEAN > > +EFIAPI > > +CoDCheckCapsuleOnDiskFlag( > > + VOID > > + ) > > +{ > > + EFI_STATUS Status; > > + UINT64 OsIndication; > > + UINTN DataSize; > > + > > + // > > + // Check File Capsule Delivery Supported Flag in OsIndication varia= ble > > + // > > + OsIndication =3D 0; > > + DataSize =3D sizeof(UINT64); > > + Status =3D gRT->GetVariable ( > > + EFI_OS_INDICATIONS_VARIABLE_NAME, > > + &gEfiGlobalVariableGuid, > > + NULL, > > + &DataSize, > > + &OsIndication > > + ); > > + if (!EFI_ERROR(Status) && > > + (OsIndication & > > EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED) !=3D 0) { > > + return TRUE; > > + } > > + > > + return FALSE; > > +} > > + > > + > > +/** > > + This routine is called to clear CapsuleOnDisk flags including OsInd= ications > > and BootNext variable. > > + > > + @retval EFI_SUCCESS All Capsule On Disk flags are cleared > > + > > +**/ > > +EFI_STATUS > > +EFIAPI > > +CoDClearCapsuleOnDiskFlag( > > + VOID > > + ) > > +{ > > + EFI_STATUS Status; > > + UINT64 OsIndication; > > + UINTN DataSize; > > + > > + // > > + // Reset File Capsule Delivery Supported Flag in OsIndication varia= ble > > + // > > + OsIndication =3D 0; > > + DataSize =3D sizeof(UINT64); > > + Status =3D gRT->GetVariable ( > > + EFI_OS_INDICATIONS_VARIABLE_NAME, > > + &gEfiGlobalVariableGuid, > > + NULL, > > + &DataSize, > > + &OsIndication > > + ); > > + if (EFI_ERROR(Status) || > > + (OsIndication & > > EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED) =3D=3D 0) { > > + return Status; > > + } > > + > > + OsIndication &=3D > > ~((UINT64)EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED); > > + Status =3D gRT->SetVariable ( > > + EFI_OS_INDICATIONS_VARIABLE_NAME, > > + &gEfiGlobalVariableGuid, > > + EFI_VARIABLE_BOOTSERVICE_ACCESS | > > EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, > > + sizeof(UINT64), > > + &OsIndication > > + ); > > + ASSERT(!EFI_ERROR(Status)); > > + > > + // > > + // Delete BootNext variable. Capsule Process may reset system, so c= an't > > rely on Bds to clear this variable > > + // > > + Status =3D gRT->SetVariable ( > > + EFI_BOOT_NEXT_VARIABLE_NAME, > > + &gEfiGlobalVariableGuid, > > + 0, > > + 0, > > + NULL > > + ); > > + ASSERT (Status =3D=3D EFI_SUCCESS || Status =3D=3D EFI_NOT_FOUND); > > + > > + return EFI_SUCCESS; > > +} > > + > > +/** > > + This routine is called to clear Capsule On Disk Relocation flag > > + The flag is the total size of capsules being relocated. It is saved > > + in CapsuleOnDisk Relocation Info varible in form of UINT64 > > + > > + @param[out] CapsuleRelocInfo The value of "CapsuleRelocInfo" varia= ble > > + > > + @retval EFI_SUCCESS Capsule Relocation flag is cleared > > + > > +**/ > > +EFI_STATUS > > +CoDCheckCapsuleRelocationInfo( > > + OUT BOOLEAN *CapsuleRelocInfo > > + ) >=20 >=20 > I do not see the above function being used internally/externally. > Please help to check and remove it. >=20 >=20 > > +{ > > + EFI_STATUS Status; > > + UINTN DataSize; > > + > > + DataSize =3D sizeof(BOOLEAN); > > + > > + Status=3D gRT->GetVariable ( > > + COD_RELOCATION_INFO_VAR_NAME, > > + &gEfiCapsuleVendorGuid, > > + NULL, > > + &DataSize, > > + CapsuleRelocInfo > > + ); > > + > > + if (DataSize !=3D sizeof(BOOLEAN)) { > > + return EFI_INVALID_PARAMETER; > > + } > > + > > + return Status; > > +} > > + > > +/** > > + This routine is called to clear CapsuleOnDisk Relocation Info varia= ble. > > + Total Capsule On Disk length is recorded in this variable > > + > > + @retval EFI_SUCCESS Capsule On Disk flags are cleared > > + > > +**/ > > +EFI_STATUS > > +CoDClearCapsuleRelocationInfo( > > + VOID > > + ) > > +{ > > + return gRT->SetVariable ( > > + COD_RELOCATION_INFO_VAR_NAME, > > + &gEfiCapsuleVendorGuid, > > + 0, > > + 0, > > + NULL > > + ); > > +} > > + > > +/** > > + Relocate Capsule on Disk from EFI system partition to a platform-sp= ecific > > NV storage device > > + with BlockIo protocol. Relocation device path, identified by > > PcdCodRelocationDevPath, must > > + be a full device path. > > + Device enumeration like USB costs time, user can input MaxRetry to = tell > > function to retry. > > + Function will stall 100ms between each retry. > > + > > + Side Effects: > > + Content corruption. Block IO write directly touches low level wri= te. > Orignal > > partitions, file systems > > + of the relocation device will be corrupted. > > + > > + @param[in] MaxRetry Max Connection Retry. Stall 100m= s > between > > each connection try to ensure > > + devices like USB can get enumera= ted. > > + > > + @retval EFI_SUCCESS Capsule on Disk images are sucessfully reloca= ted > to > > the platform-specific device. > > + > > +**/ > > +EFI_STATUS > > +EFIAPI >=20 >=20 > Please help to remove 'EFIAPI' for this internal function. >=20 >=20 > > +RelocateCapsuleToDisk( > > + UINTN MaxRetry > > + ) > > +{ > > + EFI_STATUS Status; > > + UINTN CapsuleOnDiskNum; > > + UINTN Index; > > + UINTN DataSize; > > + UINT64 TotalImageSize; > > + UINT64 TotalImageNameSize; > > + IMAGE_INFO *CapsuleOnDiskBuf; > > + EFI_HANDLE Handle; > > + EFI_HANDLE TempHandle; > > + EFI_HANDLE *HandleBuffer; > > + UINTN NumberOfHandles; > > + EFI_BLOCK_IO_PROTOCOL *BlockIo; > > + UINT8 *CapsuleDataBuf; > > + UINT8 *CapsulePtr; > > + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Fs; > > + EFI_FILE_HANDLE RootDir; > > + EFI_FILE_HANDLE TempCodFile; > > + UINT64 TempCodFileSize; > > + EFI_DEVICE_PATH *TempDevicePath; > > + BOOLEAN RelocationInfo; > > + UINT16 LoadOptionNumber; > > + EFI_CAPSULE_HEADER FileNameCapsuleHeader; > > + > > + RootDir =3D NULL; > > + TempCodFile =3D NULL; > > + HandleBuffer =3D NULL; > > + CapsuleDataBuf =3D NULL; > > + CapsuleOnDiskBuf =3D NULL; > > + NumberOfHandles =3D 0; > > + > > + DEBUG ((DEBUG_INFO, "CapsuleOnDisk RelocateCapsule Enter\n")); > > + > > + // > > + // 1. Load all Capsule On Disks in to memory > > + // > > + Status =3D GetAllCapsuleOnDisk(MaxRetry, &CapsuleOnDiskBuf, > > &CapsuleOnDiskNum, &Handle, &LoadOptionNumber); > > + if (EFI_ERROR(Status) || CapsuleOnDiskNum =3D=3D 0) { > > + DEBUG ((DEBUG_INFO, "RelocateCapsule: GetAllCapsuleOnDisk Status = - > > 0x%x\n", Status)); > > + return EFI_NOT_FOUND; > > + } > > + > > + // > > + // 2. Connect platform special dev path or Use EFI System Partition= as > > relocation device > > + // > > + if (PcdGetSize(PcdCodRelocationDevPath) > > > sizeof(EFI_DEVICE_PATH_PROTOCOL)) { >=20 >=20 > Do we need a validity check for the device path specified by > 'PcdCodRelocationDevPath'? Since it is from external input (by configuri= ng > the PCD). >=20 > Also, should we consider an error when the above 'if' statement is not m= et? >=20 > For the implementation in the patch, when: > if (PcdGetSize(PcdCodRelocationDevPath) > > sizeof(EFI_DEVICE_PATH_PROTOCOL)) { > evaluates to false, 'Handle' will still carry the value for the device w= here > the capsules are placed. And then, the function may continue to write > content > on this media device. I think this should not happen, right? >=20 No, that's how it is designed. PcdCodRelocationDevPath is used by platform to specify a device to store t= emp Cod relocation file.=20 If this PCD is not available, it means that platform doesn't have a requir= ement to store the file to a specific place. Then save the file to the device where the capsules are placed. >=20 > > + Status =3D EfiBootManagerConnectDevicePath ((EFI_DEVICE_PATH > > *)PcdGetPtr(PcdCodRelocationDevPath), &TempHandle); > > + if (EFI_ERROR(Status)) { > > + DEBUG ((DEBUG_ERROR, "RelocateCapsule: > > EfiBootManagerConnectDevicePath Status - 0x%x\n", Status)); > > + goto EXIT; > > + } > > + > > + // > > + // Connect all the child handle. Partition & FAT drivers are allo= wed in this > > case > > + // > > + gBS->ConnectController (TempHandle, NULL, NULL, TRUE); > > + Status =3D gBS->LocateHandleBuffer( > > + ByProtocol, > > + &gEfiSimpleFileSystemProtocolGuid, > > + NULL, > > + &NumberOfHandles, > > + &HandleBuffer > > + ); > > + if (EFI_ERROR(Status)) { > > + DEBUG ((DEBUG_ERROR, "RelocateCapsule: LocateHandleBuffer > Status - > > 0x%x\n", Status)); > > + goto EXIT; > > + } > > + > > + // > > + // Find first Simple File System Handle which can match > > PcdCodRelocationDevPath > > + // > > + for (Index =3D 0; Index < NumberOfHandles; Index++) { > > + Status =3D gBS->HandleProtocol(HandleBuffer[Index], > > &gEfiDevicePathProtocolGuid, (VOID **)&TempDevicePath); > > + if (EFI_ERROR(Status)) { > > + continue; > > + } > > + > > + DataSize =3D GetDevicePathSize((EFI_DEVICE_PATH > > *)PcdGetPtr(PcdCodRelocationDevPath)) - sizeof(EFI_DEVICE_PATH); > > + if (0 =3D=3D CompareMem((EFI_DEVICE_PATH > > *)PcdGetPtr(PcdCodRelocationDevPath), TempDevicePath, DataSize)) { > > + Handle =3D HandleBuffer[Index]; > > + break; > > + } > > + } > > + > > + FreePool(HandleBuffer); > > + > > + if (Index =3D=3D NumberOfHandles) { > > + DEBUG ((DEBUG_ERROR, "RelocateCapsule: No simple file system > > protocol found.\n")); > > + Status =3D EFI_NOT_FOUND; > > + } > > + } > > + > > + Status =3D gBS->HandleProtocol(Handle, &gEfiBlockIoProtocolGuid, (V= OID > > **)&BlockIo); > > + if (EFI_ERROR(Status) || BlockIo->Media->ReadOnly) { > > + DEBUG((DEBUG_ERROR, "Fail to find Capsule on Disk relocation Bloc= kIo > > device or device is ReadOnly!\n")); > > + return Status; > > + } > > + > > + Status =3D gBS->HandleProtocol(Handle, > &gEfiSimpleFileSystemProtocolGuid, > > (VOID **)&Fs); > > + if (EFI_ERROR(Status)) { > > + return Status; > > + } > > + > > + // > > + // Check if device used to relocate Capsule On Disk is big enough > > + // > > + TotalImageSize =3D 0; > > + TotalImageNameSize =3D 0; > > + for (Index =3D 0; Index < CapsuleOnDiskNum; Index++) { > > + // > > + // Overflow check > > + // > > + if (MAX_ADDRESS - (UINTN)TotalImageSize <=3D > > CapsuleOnDiskBuf[Index].FileInfo->FileSize) { > > + return EFI_INVALID_PARAMETER; >=20 >=20 > Will memory leak happen in this error handling? >=20 >=20 > > + } > > + > > + if (MAX_ADDRESS - (UINTN)TotalImageNameSize <=3D > > StrSize(CapsuleOnDiskBuf[Index].FileInfo->FileName)) { > > + return EFI_INVALID_PARAMETER; > > + } > > + > > + TotalImageSize +=3D CapsuleOnDiskBuf[Index].FileInfo->FileSiz= e; > > + TotalImageNameSize +=3D StrSize(CapsuleOnDiskBuf[Index].FileInfo- > > >FileName); > > + DEBUG((DEBUG_INFO, "RelocateCapsule: %x > > Size %x\n",CapsuleOnDiskBuf[Index].FileInfo->FileName, > > CapsuleOnDiskBuf[Index].FileInfo->FileSize)); > > + } > > + > > + DEBUG((DEBUG_INFO, "RelocateCapsule: TotalImageSize %x\n", > > TotalImageSize)); > > + DEBUG((DEBUG_INFO, "RelocateCapsule: TotalImageNameSize %x\n", > > TotalImageNameSize)); > > + > > + if (MAX_ADDRESS - (UINTN)TotalImageNameSize <=3D sizeof(UINT64) * 2 > || > > + MAX_ADDRESS - (UINTN)TotalImageSize <=3D > > (UINTN)TotalImageNameSize + sizeof(UINT64) * 2) { > > + return EFI_INVALID_PARAMETER; > > + } > > + > > + TempCodFileSize =3D sizeof(UINT64) + TotalImageSize + > > sizeof(EFI_CAPSULE_HEADER) + TotalImageNameSize; > > + > > + // > > + // Check if CapsuleTotalSize. There could be reminder, so use LastB= lock > > number directly > > + // > > + if (DivU64x32(TempCodFileSize, BlockIo->Media->BlockSize) > BlockIo= - > > >Media->LastBlock) { > > + DEBUG((DEBUG_ERROR, "RelocateCapsule: Relocation device isn't big > > enough to hold all Capsule on Disk!\n")); > > + DEBUG((DEBUG_ERROR, "TotalImageSize =3D %x\n", TotalImageSize)); > > + DEBUG((DEBUG_ERROR, "TotalImageNameSize =3D %x\n", > > TotalImageNameSize)); > > + DEBUG((DEBUG_ERROR, "RelocationDev BlockSize =3D %x LastBlock > =3D %x\n", > > BlockIo->Media->BlockSize, BlockIo->Media->LastBlock)); > > + Status =3D EFI_OUT_OF_RESOURCES; > > + goto EXIT; > > + } > > + > > + CapsuleDataBuf =3D AllocatePool((UINTN) TempCodFileSize); > > + if (CapsuleDataBuf =3D=3D NULL) { > > + Status =3D EFI_OUT_OF_RESOURCES; > > + goto EXIT; > > + } > > + > > + // > > + // First UINT64 reserved for total image size, including capsule na= me > > capsule. > > + // > > + *(UINT64 *) CapsuleDataBuf =3D TotalImageSize + > > sizeof(EFI_CAPSULE_HEADER) + TotalImageNameSize; > > + > > + // > > + // Line up all the Capsule on Disk and write to relocation disk at = one time. > It > > could save some time in disk write > > + // > > + for (Index =3D 0, CapsulePtr =3D CapsuleDataBuf + sizeof(UINT64); I= ndex < > > CapsuleOnDiskNum; Index++) { > > + CopyMem(CapsulePtr, CapsuleOnDiskBuf[Index].ImageAddress, > (UINTN) > > CapsuleOnDiskBuf[Index].FileInfo->FileSize); > > + CapsulePtr +=3D CapsuleOnDiskBuf[Index].FileInfo->FileSize; > > + } > > + > > + // > > + // Line the capsule header for capsule name capsule. > > + // > > + CopyGuid(&FileNameCapsuleHeader.CapsuleGuid, > > &gEdkiiCapsuleOnDiskNameGuid); > > + FileNameCapsuleHeader.CapsuleImageSize =3D (UINT32) > > TotalImageNameSize + sizeof(EFI_CAPSULE_HEADER); > > + FileNameCapsuleHeader.Flags =3D > > CAPSULE_FLAGS_PERSIST_ACROSS_RESET; > > + FileNameCapsuleHeader.HeaderSize =3D sizeof(EFI_CAPSULE_HEADE= R); > > + CopyMem(CapsulePtr, &FileNameCapsuleHeader, > > FileNameCapsuleHeader.HeaderSize); > > + CapsulePtr +=3D FileNameCapsuleHeader.HeaderSize; > > + > > + // > > + // Line up all the Capsule file names. > > + // > > + for (Index =3D 0; Index < CapsuleOnDiskNum; Index++) { > > + CopyMem(CapsulePtr, CapsuleOnDiskBuf[Index].FileInfo->FileName, > > StrSize(CapsuleOnDiskBuf[Index].FileInfo->FileName)); > > + CapsulePtr +=3D StrSize(CapsuleOnDiskBuf[Index].FileInfo->FileNam= e); > > + } > > + > > + // > > + // 5. Flash all Capsules on Disk to TempCoD.tmp under RootDir > > + // > > + Status =3D Fs->OpenVolume(Fs, &RootDir); > > + if (EFI_ERROR(Status)) { > > + DEBUG((DEBUG_ERROR, "RelocateCapsule: OpenVolume error. %x\n", > > Status)); > > + goto EXIT; > > + } > > + > > + Status =3D RootDir->Open( > > + RootDir, > > + &TempCodFile, > > + (CHAR16 *)PcdGetPtr(PcdCoDRelocationFileName), > > + EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE, > > + 0 > > + ); > > + if (!EFI_ERROR(Status)) { > > + // > > + // Error handling code to prevent malicious code to hold this fil= e to block > > capsule on disk > > + // > > + TempCodFile->Delete(TempCodFile); > > + } > > + Status =3D RootDir->Open( > > + RootDir, > > + &TempCodFile, > > + (CHAR16 *)PcdGetPtr(PcdCoDRelocationFileName), > > + EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | > > EFI_FILE_MODE_CREATE, > > + 0 > > + ); > > + if (EFI_ERROR(Status)) { > > + DEBUG((DEBUG_ERROR, "RelocateCapsule: Open TemCoD.tmp > > error. %x\n", Status)); > > + goto EXIT; > > + } > > + > > + // > > + // Always write at the begining of TempCap file > > + // > > + DataSize =3D (UINTN) TempCodFileSize; > > + Status =3D TempCodFile->Write( > > + TempCodFile, > > + &DataSize, > > + CapsuleDataBuf > > + ); > > + if (EFI_ERROR(Status)) { > > + DEBUG((DEBUG_ERROR, "RelocateCapsule: Write TemCoD.tmp > > error. %x\n", Status)); > > + goto EXIT; > > + } > > + > > + if (DataSize !=3D TempCodFileSize) { > > + Status =3D EFI_DEVICE_ERROR; > > + goto EXIT; > > + } > > + > > + // > > + // Save Capsule On Disk relocation info to "CodRelocationInfo" Var > > + // It is used in next reboot by TCB > > + // > > + RelocationInfo =3D TRUE; > > + Status =3D gRT->SetVariable( > > + COD_RELOCATION_INFO_VAR_NAME, > > + &gEfiCapsuleVendorGuid, > > + EFI_VARIABLE_NON_VOLATILE | > > EFI_VARIABLE_BOOTSERVICE_ACCESS, > > + sizeof (BOOLEAN), > > + &RelocationInfo > > + ); > > + // > > + // Save the LoadOptionNumber of the boot option, where the capsule = is > > relocated, > > + // into "CodRelocationLoadOption" var. It is used in next reboot af= ter > > capsule is > > + // updated out of TCB to remove the TempCoDFile. > > + // > > + Status =3D gRT->SetVariable( > > + COD_RELOCATION_LOAD_OPTION_VAR_NAME, > > + &gEfiCapsuleVendorGuid, > > + EFI_VARIABLE_NON_VOLATILE | > > EFI_VARIABLE_BOOTSERVICE_ACCESS, > > + sizeof (UINT16), > > + &LoadOptionNumber > > + ); > > + > > +EXIT: > > + > > + if (CapsuleDataBuf !=3D NULL) { > > + FreePool(CapsuleDataBuf); > > + } > > + > > + if (CapsuleOnDiskBuf !=3D NULL) { > > + // > > + // Free resources allocated by CodLibGetAllCapsuleOnDisk > > + // > > + for (Index =3D 0; Index < CapsuleOnDiskNum; Index++ ) { > > + FreePool(CapsuleOnDiskBuf[Index].ImageAddress); > > + FreePool(CapsuleOnDiskBuf[Index].FileInfo); > > + } > > + FreePool(CapsuleOnDiskBuf); > > + } > > + > > + if (TempCodFile !=3D NULL) { > > + if (EFI_ERROR(Status)) { > > + TempCodFile->Delete (TempCodFile); > > + } else { > > + TempCodFile->Close (TempCodFile); > > + } > > + } > > + > > + if (RootDir !=3D NULL) { > > + RootDir->Close (RootDir); > > + } > > + > > + return Status; > > +} > > + > > +/** > > + For the platforms that support Capsule In Ram, reuse the Capsule In= Ram > > to deliver capsule. > > + Relocate Capsule On Disk to memory and call UpdateCapsule(). > > + Device enumeration like USB costs time, user can input MaxRetry to = tell > > function to retry. > > + Function will stall 100ms between each retry. > > + > > + @param[in] MaxRetry Max Connection Retry. Stall 100m= s > between > > each connection try to ensure > > + devices like USB can get enumera= ted. > > + > > + @retval EFI_SUCCESS Deliver capsule through Capsule In Ram > successfully. > > + > > +**/ > > +EFI_STATUS > > +EFIAPI >=20 > Please help to remove 'EFIAPI' for this internal function. >=20 >=20 > > +RelocateCapsuleToRam ( > > + UINTN MaxRetry > > + ) > > +{ > > + EFI_STATUS Status; > > + UINTN CapsuleOnDiskNum; > > + IMAGE_INFO *CapsuleOnDiskBuf; > > + EFI_HANDLE Handle; > > + EFI_CAPSULE_BLOCK_DESCRIPTOR *BlockDescriptors; > > + VOID **CapsuleBuffer; > > + UINTN *CapsuleSize; > > + EFI_CAPSULE_HEADER *FileNameCapsule; > > + UINTN Index; > > + UINT8 *StringBuf; > > + UINTN StringSize; > > + UINTN TotalStringSize; > > + > > + CapsuleOnDiskBuf =3D NULL; > > + BlockDescriptors =3D NULL; > > + CapsuleBuffer =3D NULL; > > + CapsuleSize =3D NULL; > > + FileNameCapsule =3D NULL; > > + TotalStringSize =3D 0; > > + > > + // > > + // 1. Load all Capsule On Disks into memory > > + // > > + Status =3D GetAllCapsuleOnDisk (MaxRetry, &CapsuleOnDiskBuf, > > &CapsuleOnDiskNum, &Handle, NULL); > > + if (EFI_ERROR (Status) || CapsuleOnDiskNum =3D=3D 0) { > > + DEBUG ((DEBUG_ERROR, "GetAllCapsuleOnDisk Status - 0x%x\n", > > Status)); > > + return EFI_NOT_FOUND; > > + } > > + > > + // > > + // 2. Add a capsule for Capsule file name strings > > + // > > + CapsuleBuffer =3D AllocateZeroPool ((CapsuleOnDiskNum + 1) * sizeof > (VOID > > *)); > > + if (CapsuleBuffer =3D=3D NULL) { > > + DEBUG ((DEBUG_ERROR, "Fail to allocate memory for capsules.\n")); > > + return EFI_OUT_OF_RESOURCES; > > + } > > + > > + CapsuleSize =3D AllocateZeroPool ((CapsuleOnDiskNum + 1) * sizeof > > (UINTN)); > > + if (CapsuleSize =3D=3D NULL) { > > + DEBUG ((DEBUG_ERROR, "Fail to allocate memory for capsules.\n")); > > + return EFI_OUT_OF_RESOURCES; >=20 >=20 > Potential memory leaks in some error handling paths, please help to > address them. >=20 >=20 > > + } > > + > > + for (Index =3D 0; Index < CapsuleOnDiskNum; Index++) { > > + CapsuleBuffer[Index] =3D (VOID *)(UINTN) > > CapsuleOnDiskBuf[Index].ImageAddress; > > + CapsuleSize[Index] =3D (UINTN) CapsuleOnDiskBuf[Index].FileInfo- > >FileSize; > > + TotalStringSize +=3D StrSize (CapsuleOnDiskBuf[Index].FileInfo- > >FileName); > > + } > > + > > + FileNameCapsule =3D AllocateZeroPool (sizeof (EFI_CAPSULE_HEADER) + > > TotalStringSize); > > + if (FileNameCapsule =3D=3D NULL) { > > + DEBUG ((DEBUG_ERROR, "Fail to allocate memory for name > capsule.\n")); > > + return EFI_OUT_OF_RESOURCES; > > + } > > + > > + FileNameCapsule->CapsuleImageSize =3D (UINT32) (sizeof > > (EFI_CAPSULE_HEADER) + TotalStringSize); > > + FileNameCapsule->Flags =3D CAPSULE_FLAGS_PERSIST_ACROSS_RESET; > > + FileNameCapsule->HeaderSize =3D sizeof (EFI_CAPSULE_HEADER); > > + CopyGuid (&(FileNameCapsule->CapsuleGuid), > > &gEdkiiCapsuleOnDiskNameGuid); > > + > > + StringBuf =3D (UINT8 *)FileNameCapsule + FileNameCapsule->HeaderSiz= e; > > + for (Index =3D 0; Index < CapsuleOnDiskNum; Index ++) { > > + StringSize =3D StrSize (CapsuleOnDiskBuf[Index].FileInfo->FileNam= e); > > + CopyMem (StringBuf, CapsuleOnDiskBuf[Index].FileInfo->FileName, > > StringSize); > > + StringBuf +=3D StringSize; > > + } > > + > > + CapsuleBuffer[CapsuleOnDiskNum] =3D FileNameCapsule; > > + CapsuleSize[CapsuleOnDiskNum] =3D TotalStringSize + sizeof > > (EFI_CAPSULE_HEADER); > > + > > + // > > + // 3. Build Gather list for the capsules > > + // > > + Status =3D BuildGatherList (CapsuleBuffer, CapsuleSize, > CapsuleOnDiskNum > > + 1, &BlockDescriptors); > > + if (EFI_ERROR (Status) || BlockDescriptors =3D=3D NULL) { > > + return EFI_OUT_OF_RESOURCES; > > + } > > + > > + // > > + // 4. Call UpdateCapsule() service > > + // > > + Status =3D gRT->UpdateCapsule((EFI_CAPSULE_HEADER **) CapsuleBuffer= , > > CapsuleOnDiskNum + 1, (UINTN) BlockDescriptors); > > + > > + return Status; > > +} > > + > > +/** > > + Relocate Capsule on Disk from EFI system partition. > > + > > + Two solution to deliver Capsule On Disk: > > + Solution A: If PcdCapsuleInRamSupport is enabled, relocate Capsule = On > > Disk to memory and call UpdateCapsule(). > > + Solution B: If PcdCapsuleInRamSupport is disabled, relocate Capsule= On > > Disk to a platform-specific NV storage > > + device with BlockIo protocol. > > + > > + Device enumeration like USB costs time, user can input MaxRetry to = tell > > function to retry. > > + Function will stall 100ms between each retry. > > + > > + Side Effects: > > + Capsule Delivery Supported Flag in OsIndication variable and Boot= Next > > variable will be cleared. > > + Solution B: Content corruption. Block IO write directly touches l= ow level > > write. Orignal partitions, file > > + systems of the relocation device will be corrupted. > > + > > + @param[in] MaxRetry Max Connection Retry. Stall 100m= s > between > > each connection try to ensure > > + devices like USB can get enumera= ted. > > + > > + @retval EFI_SUCCESS Capsule on Disk images are sucessfully reloca= ted. > > + > > +**/ > > +EFI_STATUS > > +EFIAPI > > +CoDRelocateCapsule( > > + UINTN MaxRetry > > + ) > > +{ > > + if (!PcdGetBool (PcdCapsuleOnDiskSupport)) { > > + return EFI_UNSUPPORTED; > > + } > > + > > + // > > + // Clear CapsuleOnDisk Flag firstly. > > + // > > + CoDClearCapsuleOnDiskFlag (); > > + > > + // > > + // If Capsule In Ram is supported, delivery capsules through memory > > + // > > + if (PcdGetBool (PcdCapsuleInRamSupport)) { > > + DEBUG ((DEBUG_INFO, "Capsule In Ram is supported, call gRT- > > >UpdateCapsule().\n")); > > + return RelocateCapsuleToRam (MaxRetry); > > + } else { > > + DEBUG ((DEBUG_INFO, "Reallcoate all Capsule on Disks to %s in > > RootDir.\n", (CHAR16 *)PcdGetPtr(PcdCoDRelocationFileName))); > > + return RelocateCapsuleToDisk (MaxRetry); > > + } > > +} > > + > > +/** > > + Remove the temp file from the root of EFI System Partition. > > + Device enumeration like USB costs time, user can input MaxRetry to = tell > > function to retry. > > + Function will stall 100ms between each retry. > > + > > + @param[in] MaxRetry Max Connection Retry. Stall 100m= s > between > > each connection try to ensure > > + devices like USB can get enumera= ted. > > + > > + @retval EFI_SUCCESS Remove the temp file successfully. > > + > > +**/ > > +EFI_STATUS > > +EFIAPI > > +CoDRemoveTempFile ( > > + UINTN MaxRetry > > + ) > > +{ > > + EFI_STATUS Status; > > + UINTN DataSize; > > + UINT16 *LoadOptionNumber; > > + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Fs; > > + EFI_HANDLE FsHandle; > > + EFI_FILE_HANDLE RootDir; > > + EFI_FILE_HANDLE TempCodFile; > > + > > + RootDir =3D NULL; > > + TempCodFile =3D NULL; > > + > > + LoadOptionNumber =3D AllocatePool (sizeof(UINT16)); > > + DataSize =3D sizeof(UINT16); > > + > > + // > > + // Check if capsule files are relocated > > + // > > + Status =3D gRT->GetVariable ( > > + COD_RELOCATION_LOAD_OPTION_VAR_NAME, > > + &gEfiCapsuleVendorGuid, > > + NULL, > > + &DataSize, > > + (VOID *)LoadOptionNumber > > + ); > > + if (EFI_ERROR(Status) || DataSize !=3D sizeof(UINT16)) { > > + return Status; >=20 >=20 > Please handle possible memory leak in error handlings for this function. >=20 >=20 > > + } > > + > > + // > > + // Get the EFI file system from the boot option where the capsules = are > > relocated > > + // > > + Status =3D GetEfiSysPartitionFromActiveBootOption(MaxRetry, > > &LoadOptionNumber, &FsHandle); > > + if (EFI_ERROR(Status)) { > > + return Status; > > + } > > + > > + Status =3D gBS->HandleProtocol(FsHandle, > > &gEfiSimpleFileSystemProtocolGuid, (VOID **)&Fs); > > + if (EFI_ERROR(Status)) { > > + return Status; > > + } > > + > > + Status =3D Fs->OpenVolume(Fs, &RootDir); > > + if (EFI_ERROR(Status)) { > > + return Status; > > + } > > + > > + // > > + // Delete the TempCoDFile > > + // > > + Status =3D RootDir->Open( > > + RootDir, > > + &TempCodFile, > > + (CHAR16 *)PcdGetPtr(PcdCoDRelocationFileName), > > + EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE, > > + 0 > > + ); > > + if (!EFI_ERROR(Status)) { > > + TempCodFile->Delete(TempCodFile); > > + } > > + > > + if (RootDir !=3D NULL) { > > + RootDir->Close(RootDir); > > + } > > + > > + // > > + // Clear "CoDRelocationLoadOption" variable > > + // > > + Status =3D gRT->SetVariable ( > > + COD_RELOCATION_LOAD_OPTION_VAR_NAME, > > + &gEfiCapsuleVendorGuid, > > + 0, > > + 0, > > + NULL > > + ); > > + > > + return EFI_SUCCESS; > > +} > > diff --git a/MdeModulePkg/Library/DxeCapsuleLibFmp/CapsuleOnDisk.h > > b/MdeModulePkg/Library/DxeCapsuleLibFmp/CapsuleOnDisk.h > > new file mode 100644 > > index 0000000000..064dc791b8 > > --- /dev/null > > +++ b/MdeModulePkg/Library/DxeCapsuleLibFmp/CapsuleOnDisk.h > > @@ -0,0 +1,63 @@ > > +/** @file > > + Defines several datastructures used by Capsule On Disk feature. > > + They are mainly used for FAT files. > > + > > + Copyright (c) 2019, Intel Corporation. All rights reserved.
> > + SPDX-License-Identifier: BSD-2-Clause-Patent > > + > > +**/ > > + > > +#ifndef _CAPSULES_ON_DISK_H_ > > +#define _CAPSULES_ON_DISK_H_ > > + > > +#include > > +#include > > + > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > + > > +#include > > +#include > > +#include > > + > > +#include > > +#include > > + > > +// > > +// This data structure is the part of FILE_INFO_ENTRY > > +// > > +#define FILE_INFO_SIGNATURE SIGNATURE_32 ('F', 'L', 'I', 'F') > > + > > +// > > +// LoadOptionNumber of the boot option where the capsules is relocate= d. > > +// > > +#define COD_RELOCATION_LOAD_OPTION_VAR_NAME > > L"CodRelocationLoadOption" > > + > > +typedef struct { > > + UINTN Signature; > > + LIST_ENTRY Link; /// Linked list members. > > + EFI_FILE_INFO *FileInfo; /// Pointer to the FileInfo= struct for this > > file or NULL. > > + CHAR16 *FileNameFirstPart; /// Text to the left of rig= ht-most > period > > in the file name. String is capitialized > > + CHAR16 *FileNameSecondPart; /// Text to the right of ri= ght-most > > period in the file name.String is capitialized. Maybe NULL > > +} FILE_INFO_ENTRY; > > + > > +// > > +// (20 * (6+5+2))+1) unicode characters from EFI FAT spec (doubled fo= r > > bytes) > > +// > > +#define MAX_FILE_NAME_SIZE 522 > > +#define MAX_FILE_NAME_LEN (MAX_FILE_NAME_SIZE / > sizeof(CHAR16)) > > + > > +#define MAX_FILE_INFO_LEN (OFFSET_OF(EFI_FILE_INFO, FileName) + > > MAX_FILE_NAME_LEN) > > + > > +#endif // _CAPSULES_ON_DISK_H_ > > diff --git a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.c > > b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.c > > index f38ab69e38..4254cc8270 100644 > > --- a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.c > > +++ b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.c > > @@ -8,11 +8,11 @@ > > > > SupportCapsuleImage(), ProcessCapsuleImage(), IsValidCapsuleHeader(= ), > > ValidateFmpCapsule(), and DisplayCapsuleImage() receives untrusted > input > > and > > performs basic validation. > > > > - Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<= BR> > > + Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<= BR> > > SPDX-License-Identifier: BSD-2-Clause-Patent > > > > **/ > > > > #include > > @@ -88,11 +88,12 @@ EFI_STATUS > > RecordFmpCapsuleStatusVariable ( > > IN EFI_CAPSULE_HEADER *CapsuleHeader, > > IN EFI_STATUS CapsuleStatus, > > IN UINTN PayloadIndex, > > IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER > > *ImageHeader, > > - IN EFI_DEVICE_PATH_PROTOCOL *FmpDevicePath OPT= IONAL > > + IN EFI_DEVICE_PATH_PROTOCOL *FmpDevicePath, OP= TIONAL > > + IN CHAR16 *CapFileName OP= TIONAL >=20 >=20 > Please help to update the function description comments for adding a new > parameter. >=20 > Also, the implementations of this function in file DxeCapsuleReportLib.c= & > DxeCapsuleReportLibNull.c are with different interface definitions. Coul= d > you help to double confirm on this? >=20 It is a mistake, will fix it. >=20 > > ); > > > > /** > > Function indicate the current completion progress of the firmware > > update. Platform may override with own specific progress function. > > @@ -107,10 +108,26 @@ EFI_STATUS > > EFIAPI > > UpdateImageProgress ( > > IN UINTN Completion > > ); > > > > +/** > > + Return if this capsule is a capsule name capsule, based upon > > CapsuleHeader. > > + > > + @param[in] CapsuleHeader A pointer to EFI_CAPSULE_HEADER > > + > > + @retval TRUE It is a capsule name capsule. > > + @retval FALSE It is not a capsule name capsule. > > +**/ > > +BOOLEAN > > +IsCapsuleNameCapsule ( > > + IN EFI_CAPSULE_HEADER *CapsuleHeader > > + ) > > +{ > > + return CompareGuid (&CapsuleHeader->CapsuleGuid, > > &gEdkiiCapsuleOnDiskNameGuid); > > +} > > + > > /** > > Return if this CapsuleGuid is a FMP capsule GUID or not. > > > > @param[in] CapsuleGuid A pointer to EFI_GUID > > > > @@ -1032,23 +1049,25 @@ StartFmpImage ( > > } > > > > /** > > Record FMP capsule status. > > > > - @param[in] Handle A FMP handle. > > + @param[in] Handle A FMP handle. > > @param[in] CapsuleHeader The capsule image header > > @param[in] CapsuleStatus The capsule process stauts > > @param[in] PayloadIndex FMP payload index > > @param[in] ImageHeader FMP image header > > + @param[in] CapFileName Capsule file name > > **/ > > VOID > > RecordFmpCapsuleStatus ( > > IN EFI_HANDLE Handle, OPTIONAL > > IN EFI_CAPSULE_HEADER *CapsuleHeader, > > IN EFI_STATUS CapsuleStatus, > > IN UINTN PayloadIndex, > > - IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER > > *ImageHeader > > + IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER > > *ImageHeader, > > + IN CHAR16 *CapFileName OPT= IONAL > > ) > > { > > EFI_STATUS Status; > > EFI_DEVICE_PATH_PROTOCOL *FmpDevicePath; > > UINT32 FmpImageInfoDescripto= rVer; > > @@ -1068,11 +1087,12 @@ RecordFmpCapsuleStatus ( > > RecordFmpCapsuleStatusVariable ( > > CapsuleHeader, > > CapsuleStatus, > > PayloadIndex, > > ImageHeader, > > - FmpDevicePath > > + FmpDevicePath, > > + CapFileName > > ); > > > > // > > // Update corresponding ESRT entry LastAttemp Status > > // > > @@ -1113,10 +1133,11 @@ RecordFmpCapsuleStatus ( > > EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER are correct. > > > > This function need support nested FMP capsule. > > > > @param[in] CapsuleHeader Points to a capsule header. > > + @param[in] CapFileName Capsule file name. > > @param[out] ResetRequired Indicates whether reset is requir= ed or > not. > > > > @retval EFI_SUCESS Process Capsule Image successfully. > > @retval EFI_UNSUPPORTED Capsule image is not supported by the > > firmware. > > @retval EFI_VOLUME_CORRUPTED FV volume in the capsule is corrupted= . > > @@ -1124,10 +1145,11 @@ RecordFmpCapsuleStatus ( > > @retval EFI_NOT_READY No FMP protocol to handle this FMP ca= psule. > > **/ > > EFI_STATUS > > ProcessFmpCapsuleImage ( > > IN EFI_CAPSULE_HEADER *CapsuleHeader, > > + IN CHAR16 *CapFileName, OPTIONAL > > OUT BOOLEAN *ResetRequired OPTIONAL > > ) > > { > > EFI_STATUS Status; > > EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER > > *FmpCapsuleHeader; > > @@ -1143,11 +1165,11 @@ ProcessFmpCapsuleImage ( > > UINTN Index2; > > BOOLEAN NotReady; > > BOOLEAN Abort; > > > > if (!IsFmpCapsuleGuid(&CapsuleHeader->CapsuleGuid)) { > > - return ProcessFmpCapsuleImage ((EFI_CAPSULE_HEADER > > *)((UINTN)CapsuleHeader + CapsuleHeader->HeaderSize), ResetRequired); > > + return ProcessFmpCapsuleImage ((EFI_CAPSULE_HEADER > > *)((UINTN)CapsuleHeader + CapsuleHeader->HeaderSize), CapFileName, > > ResetRequired); > > } > > > > NotReady =3D FALSE; > > Abort =3D FALSE; > > > > @@ -1225,11 +1247,12 @@ ProcessFmpCapsuleImage ( > > RecordFmpCapsuleStatus ( > > NULL, > > CapsuleHeader, > > EFI_NOT_READY, > > Index - FmpCapsuleHeader->EmbeddedDriverCount, > > - ImageHeader > > + ImageHeader, > > + CapFileName > > ); > > continue; > > } > > > > for (Index2 =3D 0; Index2 < NumberOfHandles; Index2++) { > > @@ -1237,11 +1260,12 @@ ProcessFmpCapsuleImage ( > > RecordFmpCapsuleStatus ( > > HandleBuffer[Index2], > > CapsuleHeader, > > EFI_ABORTED, > > Index - FmpCapsuleHeader->EmbeddedDriverCount, > > - ImageHeader > > + ImageHeader, > > + CapFileName > > ); > > continue; > > } > > > > Status =3D SetFmpImageData ( > > @@ -1260,11 +1284,12 @@ ProcessFmpCapsuleImage ( > > RecordFmpCapsuleStatus ( > > HandleBuffer[Index2], > > CapsuleHeader, > > Status, > > Index - FmpCapsuleHeader->EmbeddedDriverCount, > > - ImageHeader > > + ImageHeader, > > + CapFileName > > ); > > } > > if (HandleBuffer !=3D NULL) { > > FreePool(HandleBuffer); > > } > > @@ -1412,10 +1437,17 @@ SupportCapsuleImage ( > > // > > if (CompareGuid (&gWindowsUxCapsuleGuid, &CapsuleHeader- > > >CapsuleGuid)) { > > return EFI_SUCCESS; > > } > > > > + // > > + // Check capsule file name capsule > > + // > > + if (IsCapsuleNameCapsule(CapsuleHeader)) { > > + return EFI_SUCCESS; > > + } > > + > > if (IsFmpCapsule(CapsuleHeader)) { > > // > > // Fake capsule header is valid case in QueryCapsuleCpapbilities(= ). > > // > > if (CapsuleHeader->HeaderSize =3D=3D CapsuleHeader->CapsuleImageS= ize) { > > @@ -1434,10 +1466,11 @@ SupportCapsuleImage ( > > The firmware implements to process the capsule image. > > > > Caution: This function may receive untrusted input. > > > > @param[in] CapsuleHeader Points to a capsule header. > > + @param[in] CapFileName Capsule file name. > > @param[out] ResetRequired Indicates whether reset is requir= ed or > not. > > > > @retval EFI_SUCESS Process Capsule Image successfully. > > @retval EFI_UNSUPPORTED Capsule image is not supported by the > > firmware. > > @retval EFI_VOLUME_CORRUPTED FV volume in the capsule is corrupted= . > > @@ -1445,10 +1478,11 @@ SupportCapsuleImage ( > > **/ > > EFI_STATUS > > EFIAPI > > ProcessThisCapsuleImage ( > > IN EFI_CAPSULE_HEADER *CapsuleHeader, > > + IN CHAR16 *CapFileName, OPTIONAL > > OUT BOOLEAN *ResetRequired OPTIONAL > > ) > > { > > EFI_STATUS Status; > > > > @@ -1482,11 +1516,11 @@ ProcessThisCapsuleImage ( > > > > // > > // Process EFI FMP Capsule > > // > > DEBUG((DEBUG_INFO, "ProcessFmpCapsuleImage ...\n")); > > - Status =3D ProcessFmpCapsuleImage(CapsuleHeader, ResetRequired); > > + Status =3D ProcessFmpCapsuleImage(CapsuleHeader, CapFileName, > > ResetRequired); > > DEBUG((DEBUG_INFO, "ProcessFmpCapsuleImage - %r\n", Status)); > > > > return Status; > > } > > > > @@ -1509,11 +1543,11 @@ EFI_STATUS > > EFIAPI > > ProcessCapsuleImage ( > > IN EFI_CAPSULE_HEADER *CapsuleHeader > > ) > > { > > - return ProcessThisCapsuleImage (CapsuleHeader, NULL); > > + return ProcessThisCapsuleImage (CapsuleHeader, NULL, NULL); > > } > > > > /** > > Callback function executed when the EndOfDxe event group is signale= d. > > > > diff --git a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.inf > > b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.inf > > index 14c3d19bc3..05de4299fb 100644 > > --- a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.inf > > +++ b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.inf > > @@ -1,11 +1,11 @@ > > ## @file > > # Capsule library instance for DXE_DRIVER. > > # > > # Capsule library instance for DXE_DRIVER module types. > > # > > -# Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.=
> > +# Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.=
> > # SPDX-License-Identifier: BSD-2-Clause-Patent > > # > > ## > > > > [Defines] > > @@ -27,10 +27,12 @@ > > > > [Sources] > > DxeCapsuleLib.c > > DxeCapsuleProcessLib.c > > DxeCapsuleReportLib.c > > + CapsuleOnDisk.c > > + CapsuleOnDisk.h > > > > [Packages] > > MdePkg/MdePkg.dec > > MdeModulePkg/MdeModulePkg.dec > > > > @@ -45,10 +47,12 @@ > > ReportStatusCodeLib > > PrintLib > > HobLib > > BmpSupportLib > > DisplayUpdateProgressLib > > + FileHandleLib > > + UefiBootManagerLib > > > > [Pcd] > > gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleMax = ## > > CONSUMES > > > > > gEfiMdeModulePkgTokenSpaceGuid.PcdSystemRebootAfterCapsuleProcess > > Flag ## CONSUMES > > > > @@ -57,23 +61,38 @@ > > > > > gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleStatusCodeProcessCapsules > > End ## CONSUMES > > > > > gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleStatusCodeUpdatingFirmwa > > re ## CONSUMES > > > > > gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleStatusCodeUpdateFirmwar > > eSuccess ## CONSUMES > > > > > gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleStatusCodeUpdateFirmwar > > eFailed ## CONSUMES > > > > gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleStatusCodeResettingSyste > > m ## CONSUMES > > + gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleInRamSupport > > ## CONSUMES > > + gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleOnDiskSupport > > ## CONSUMES > > + gEfiMdeModulePkgTokenSpaceGuid.PcdCodRelocationDevPath > > ## SOMETIMES_CONSUMES > > + gEfiMdeModulePkgTokenSpaceGuid.PcdCoDRelocationFileName > > ## CONSUMES > > > > [Protocols] > > gEsrtManagementProtocolGuid ## CONSUMES > > gEfiFirmwareManagementProtocolGuid ## CONSUMES > > gEdkiiVariableLockProtocolGuid ## SOMETIMES_CONSUMES > > gEdkiiFirmwareManagementProgressProtocolGuid ## > > SOMETIMES_CONSUMES > > + gEfiSimpleFileSystemProtocolGuid ## SOMETIMES_CONSUMES > > + gEfiBlockIoProtocolGuid ## CONSUMES > > + gEfiDiskIoProtocolGuid ## CONSUMES > > > > [Guids] > > gEfiFmpCapsuleGuid ## SOMETIMES_CONSUMES ## GU= ID > > gWindowsUxCapsuleGuid ## SOMETIMES_CONSUMES ## GU= ID > > ## SOMETIMES_CONSUMES ## Variable:L"CapsuleMax" > > ## SOMETIMES_PRODUCES ## Variable:L"CapsuleMax" > > gEfiCapsuleReportGuid > > gEfiCapsuleVendorGuid ## SOMETIMES_CONSUMES ## > > Variable:L"CapsuleUpdateData" > > gEfiEndOfDxeEventGroupGuid ## CONSUMES ## Event > > + gEfiPartTypeSystemPartGuid ## SOMETIMES_CONSUMES > > + gEfiCapsuleVendorGuid ## SOMETIMES_CONSUMES ## > > Variable:L"CodRelocationInfo" > > + ## SOMETIMES_CONSUMES ## Variable:L"OsIndications" > > + ## SOMETIMES_PRODUCES ## Variable:L"OsIndications" > > + ## SOMETIMES_CONSUMES ## Variable:L"BootNext" > > + ## SOMETIMES_PRODUCES ## Variable:L"BootNext" > > + gEfiGlobalVariableGuid > > + gEdkiiCapsuleOnDiskNameGuid ## SOMETIMES_CONSUMES ## > > GUID > > > > [Depex] > > gEfiVariableWriteArchProtocolGuid > > diff --git > > a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleProcessLib.c > > b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleProcessLib.c > > index 5e2d2b87a8..e07dd7986e 100644 > > --- a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleProcessLib.c > > +++ > b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleProcessLib.c > > @@ -7,11 +7,11 @@ > > buffer overflow, integer overflow. > > > > ProcessCapsules(), ProcessTheseCapsules() will receive untrusted > > input and do basic validation. > > > > - Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<= BR> > > + Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<= BR> > > SPDX-License-Identifier: BSD-2-Clause-Patent > > > > **/ > > > > #include > > @@ -90,14 +90,45 @@ BOOLEAN > > IsValidCapsuleHeader ( > > IN EFI_CAPSULE_HEADER *CapsuleHeader, > > IN UINT64 CapsuleSize > > ); > > > > +/** > > + Return if this capsule is a capsule name capsule, based upon > > CapsuleHeader. > > + > > + @param[in] CapsuleHeader A pointer to EFI_CAPSULE_HEADER > > + > > + @retval TRUE It is a capsule name capsule. > > + @retval FALSE It is not a capsule name capsule. > > +**/ > > +BOOLEAN > > +IsCapsuleNameCapsule ( > > + IN EFI_CAPSULE_HEADER *CapsuleHeader > > + ); > > + > > +/** > > + Check the integrity of the capsule name capsule. > > + If the capsule is vaild, return the physical address of each capsul= e name > > string. > > + > > + @param[in] CapsuleHeader Pointer to the capsule header of a caps= ule > > name capsule. > > + @param[out] CapsuleNameNum Number of capsule name. > > + > > + @retval NULL Capsule name capsule is not valid. > > + @retval CapsuleNameBuf Array of capsule name physical address. > > + > > +**/ > > +EFI_PHYSICAL_ADDRESS * > > +ValidateCapsuleNameCapsuleIntegrity ( > > + IN EFI_CAPSULE_HEADER *CapsuleHeader, > > + OUT UINTN *CapsuleNameNum > > + ); > > + > > extern BOOLEAN mDxeCapsuleLibEndOfDxe; > > BOOLEAN mNeedReset =3D FALSE; > > > > VOID **mCapsulePtr; > > +CHAR16 **mCapsuleNamePtr; > > EFI_STATUS *mCapsuleStatusArray; > > UINT32 mCapsuleTotalNumber; > > > > /** > > The firmware implements to process the capsule image. > > @@ -114,10 +145,11 @@ UINT32 mCapsuleTotalNumber; > > **/ > > EFI_STATUS > > EFIAPI > > ProcessThisCapsuleImage ( > > IN EFI_CAPSULE_HEADER *CapsuleHeader, > > + IN CHAR16 *CapFileName, OPTIONAL > > OUT BOOLEAN *ResetRequired OPTIONAL > > ); > > > > /** > > Function indicate the current completion progress of the firmware > > @@ -183,20 +215,36 @@ InitCapsulePtr ( > > VOID > > ) > > { > > EFI_PEI_HOB_POINTERS HobPointer; > > UINTN Index; > > + UINTN Index2; > > + UINTN Index3; > > + UINTN CapsuleNameNumber; > > + UINTN CapsuleNameTotalNumber; > > + UINTN CapsuleNameCapsuleTotalNumber; > > + VOID **CapsuleNameCapsulePtr; > > + EFI_PHYSICAL_ADDRESS *CapsuleNameAddress; > > + > > + CapsuleNameNumber =3D 0; > > + CapsuleNameTotalNumber =3D 0; > > + CapsuleNameCapsuleTotalNumber =3D 0; > > + CapsuleNameCapsulePtr =3D NULL; > > > > // > > // Find all capsule images from hob > > // > > HobPointer.Raw =3D GetHobList (); > > while ((HobPointer.Raw =3D GetNextHob (EFI_HOB_TYPE_UEFI_CAPSULE, > > HobPointer.Raw)) !=3D NULL) { > > if (!IsValidCapsuleHeader((VOID *)(UINTN)HobPointer.Capsule- > > >BaseAddress, HobPointer.Capsule->Length)) { > > HobPointer.Header->HobType =3D EFI_HOB_TYPE_UNUSED; // Mark thi= s > > hob as invalid > > } else { > > - mCapsuleTotalNumber++; > > + if (IsCapsuleNameCapsule((VOID *)(UINTN)HobPointer.Capsule- > > >BaseAddress)) { > > + CapsuleNameCapsuleTotalNumber++; > > + } else { > > + mCapsuleTotalNumber++; > > + } > > } > > HobPointer.Raw =3D GET_NEXT_HOB (HobPointer); > > } > > > > DEBUG ((DEBUG_INFO, "mCapsuleTotalNumber - 0x%x\n", > > mCapsuleTotalNumber)); > > @@ -222,19 +270,76 @@ InitCapsulePtr ( > > mCapsuleTotalNumber =3D 0; > > return ; > > } > > SetMemN (mCapsuleStatusArray, sizeof (EFI_STATUS) * > > mCapsuleTotalNumber, EFI_NOT_READY); > > > > + if (CapsuleNameCapsuleTotalNumber !=3D 0) { > > + CapsuleNameCapsulePtr =3D (VOID **) AllocateZeroPool (sizeof (VO= ID *) > * > > CapsuleNameCapsuleTotalNumber); > > + if (CapsuleNameCapsulePtr =3D=3D NULL) { > > + DEBUG ((DEBUG_ERROR, "Allocate CapsuleNameCapsulePtr fail!\n"))= ; > > + FreePool (mCapsulePtr); > > + FreePool (mCapsuleStatusArray); > > + mCapsulePtr =3D NULL; > > + mCapsuleStatusArray =3D NULL; > > + mCapsuleTotalNumber =3D 0; > > + return ; > > + } > > + } > > + > > // > > // Find all capsule images from hob > > // > > HobPointer.Raw =3D GetHobList (); > > - Index =3D 0; > > + Index =3D 0; > > + Index2 =3D 0; > > while ((HobPointer.Raw =3D GetNextHob (EFI_HOB_TYPE_UEFI_CAPSULE, > > HobPointer.Raw)) !=3D NULL) { > > - mCapsulePtr [Index++] =3D (VOID *) (UINTN) HobPointer.Capsule- > > >BaseAddress; > > + if (!IsCapsuleNameCapsule ((VOID *) (UINTN) HobPointer.Capsule- > > >BaseAddress)) { > > + mCapsulePtr [Index++] =3D (VOID *) (UINTN) HobPointer.Capsule- > > >BaseAddress; > > + } else { > > + CapsuleNameCapsulePtr [Index2++] =3D (VOID *) (UINTN) > > HobPointer.Capsule->BaseAddress; > > + } > > HobPointer.Raw =3D GET_NEXT_HOB (HobPointer); > > } > > + > > + // > > + // Find Capsule On Disk Names > > + // > > + for (Index =3D 0; Index < CapsuleNameCapsuleTotalNumber; Index ++) = { > > + CapsuleNameAddress =3D ValidateCapsuleNameCapsuleIntegrity > > (CapsuleNameCapsulePtr[Index], &CapsuleNameNumber); > > + if (CapsuleNameAddress !=3D NULL ) { > > + CapsuleNameTotalNumber +=3D CapsuleNameNumber; > > + } > > + } > > + > > + if (CapsuleNameTotalNumber =3D=3D mCapsuleTotalNumber) { > > + mCapsuleNamePtr =3D (CHAR16 **) AllocateZeroPool (sizeof (CHAR16 = *) > * > > mCapsuleTotalNumber); > > + if (mCapsuleNamePtr =3D=3D NULL) { > > + DEBUG ((DEBUG_ERROR, "Allocate mCapsuleNamePtr fail!\n")); > > + FreePool (mCapsulePtr); > > + FreePool (mCapsuleStatusArray); > > + FreePool (CapsuleNameCapsulePtr); > > + mCapsulePtr =3D NULL; > > + mCapsuleStatusArray =3D NULL; > > + mCapsuleTotalNumber =3D 0; > > + return ; > > + } > > + > > + for (Index =3D 0, Index3 =3D 0; Index < CapsuleNameCapsuleTotalNu= mber; > > Index ++) { > > + CapsuleNameAddress =3D ValidateCapsuleNameCapsuleIntegrity > > (CapsuleNameCapsulePtr[Index], &CapsuleNameNumber); > > + if (CapsuleNameAddress !=3D NULL ) { > > + for (Index2 =3D 0; Index2 < CapsuleNameNumber; Index2 ++) { > > + mCapsuleNamePtr[Index3 ++] =3D (CHAR16 *)(UINTN) > > CapsuleNameAddress[Index2]; > > + } > > + } > > + } > > + } else { > > + mCapsuleNamePtr =3D NULL; > > + } > > + > > + if (CapsuleNameCapsulePtr !=3D NULL) { > > + FreePool (CapsuleNameCapsulePtr); > > + } > > } > > > > /** > > This function returns if all capsule images are processed. > > > > @@ -394,10 +499,11 @@ ProcessTheseCapsules ( > > EFI_CAPSULE_HEADER *CapsuleHeader; > > UINT32 Index; > > ESRT_MANAGEMENT_PROTOCOL *EsrtManagement; > > UINT16 EmbeddedDriverCount; > > BOOLEAN ResetRequired; > > + CHAR16 *CapsuleName; > > > > REPORT_STATUS_CODE(EFI_PROGRESS_CODE, (EFI_SOFTWARE | > > PcdGet32(PcdStatusCodeSubClassCapsule) | > > PcdGet32(PcdCapsuleStatusCodeProcessCapsulesBegin))); > > > > if (FirstRound) { > > InitCapsulePtr (); > > @@ -406,10 +512,11 @@ ProcessTheseCapsules ( > > if (mCapsuleTotalNumber =3D=3D 0) { > > // > > // We didn't find a hob, so had no errors. > > // > > DEBUG ((DEBUG_ERROR, "We can not find capsule data in capsule > update > > boot mode.\n")); > > + mNeedReset =3D TRUE; >=20 >=20 > According to the API description of ProcessCapsules(): >=20 > ''' > If there is no EFI_HOB_UEFI_CAPSULE, this routine does nothing. > ''' >=20 > After the above change (I assume mCapsuleTotalNumber =3D=3D 0 means no > Capsule > Hob), a system reset will be triggered. May I know the purpose for such > change? >=20 For Capsule On Disk, no capsule hob means the Cod temp relocations file is= corrupted, which also means current boot is insecure. Then force reset to re-apply normal boot platform secure policy. I will update the description. Do you have comments for it? BR, Wei Xu > Best Regards, > Hao Wu >=20 >=20 > > return EFI_SUCCESS; > > } > > > > if (AreAllImagesProcessed ()) { > > return EFI_SUCCESS; > > @@ -428,14 +535,15 @@ ProcessTheseCapsules ( > > // > > // If Windows UX capsule exist, process it first > > // > > for (Index =3D 0; Index < mCapsuleTotalNumber; Index++) { > > CapsuleHeader =3D (EFI_CAPSULE_HEADER*) mCapsulePtr [Index]; > > + CapsuleName =3D (mCapsuleNamePtr =3D=3D NULL) ? NULL : > > mCapsuleNamePtr[Index]; > > if (CompareGuid (&CapsuleHeader->CapsuleGuid, > > &gWindowsUxCapsuleGuid)) { > > DEBUG ((DEBUG_INFO, "ProcessThisCapsuleImage (Ux) - 0x%x\n", > > CapsuleHeader)); > > DEBUG ((DEBUG_INFO, "Display logo capsule is found.\n")); > > - Status =3D ProcessThisCapsuleImage (CapsuleHeader, NULL); > > + Status =3D ProcessThisCapsuleImage (CapsuleHeader, CapsuleName, > > NULL); > > mCapsuleStatusArray [Index] =3D EFI_SUCCESS; > > DEBUG((DEBUG_INFO, "ProcessThisCapsuleImage (Ux) - %r\n", > Status)); > > break; > > } > > } > > @@ -449,10 +557,11 @@ ProcessTheseCapsules ( > > if (mCapsuleStatusArray [Index] !=3D EFI_NOT_READY) { > > // already processed > > continue; > > } > > CapsuleHeader =3D (EFI_CAPSULE_HEADER*) mCapsulePtr [Index]; > > + CapsuleName =3D (mCapsuleNamePtr =3D=3D NULL) ? NULL : > > mCapsuleNamePtr[Index]; > > if (!CompareGuid (&CapsuleHeader->CapsuleGuid, > > &gWindowsUxCapsuleGuid)) { > > // > > // Call capsule library to process capsule image. > > // > > EmbeddedDriverCount =3D 0; > > @@ -469,11 +578,11 @@ ProcessTheseCapsules ( > > } > > > > if ((!FirstRound) || (EmbeddedDriverCount =3D=3D 0)) { > > DEBUG((DEBUG_INFO, "ProcessThisCapsuleImage - 0x%x\n", > > CapsuleHeader)); > > ResetRequired =3D FALSE; > > - Status =3D ProcessThisCapsuleImage (CapsuleHeader, &ResetRequ= ired); > > + Status =3D ProcessThisCapsuleImage (CapsuleHeader, CapsuleNam= e, > > &ResetRequired); > > mCapsuleStatusArray [Index] =3D Status; > > DEBUG((DEBUG_INFO, "ProcessThisCapsuleImage - %r\n", Status))= ; > > > > if (Status !=3D EFI_NOT_READY) { > > if (EFI_ERROR(Status)) { > > diff --git > > a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleReportLib.c > > b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleReportLib.c > > index 6ad766d65a..0ec5f20676 100644 > > --- a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleReportLib.c > > +++ b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleReportLib.c > > @@ -1,9 +1,9 @@ > > /** @file > > DXE capsule report related function. > > > > - Copyright (c) 2016 - 2017, Intel Corporation. All rights reserved.<= BR> > > + Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<= BR> > > SPDX-License-Identifier: BSD-2-Clause-Patent > > > > **/ > > > > #include > > @@ -27,10 +27,22 @@ > > #include > > #include > > > > #include > > > > +/** > > + This routine is called to clear CapsuleOnDisk Relocation Info varia= ble. > > + Total Capsule On Disk length is recorded in this variable > > + > > + @retval EFI_SUCCESS Capsule On Disk flags are cleared > > + > > +**/ > > +EFI_STATUS > > +CoDClearCapsuleRelocationInfo( > > + VOID > > + ); > > + > > /** > > Get current capsule last variable index. > > > > @return Current capsule last variable index. > > @retval -1 No current capsule last variable. > > @@ -172,44 +184,55 @@ RecordCapsuleStatusVariable ( > > @param[in] CapsuleHeader The capsule image header > > @param[in] CapsuleStatus The capsule process stauts > > @param[in] PayloadIndex FMP payload index > > @param[in] ImageHeader FMP image header > > @param[in] FmpDevicePath DevicePath associated with the FMP > producer > > + @param[in] CapFileName Capsule file name > > > > @retval EFI_SUCCESS The capsule status variable is recorde= d. > > @retval EFI_OUT_OF_RESOURCES No resource to record the capsule > status > > variable. > > **/ > > EFI_STATUS > > RecordFmpCapsuleStatusVariable ( > > IN EFI_CAPSULE_HEADER *CapsuleHeader, > > IN EFI_STATUS CapsuleStatus, > > IN UINTN PayloadIndex, > > IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER > > *ImageHeader, > > - IN EFI_DEVICE_PATH_PROTOCOL *FmpDevicePath OPT= IONAL > > + IN EFI_DEVICE_PATH_PROTOCOL *FmpDevicePath, OP= TIONAL > > + IN CHAR16 *CapFileName OP= TIONAL > > ) > > { > > EFI_CAPSULE_RESULT_VARIABLE_HEADER > *CapsuleResultVariableHeader; > > EFI_CAPSULE_RESULT_VARIABLE_FMP *CapsuleResultVariableFmp; > > EFI_STATUS Status; > > UINT8 *CapsuleResultVariable; > > UINTN CapsuleResultVariableSize; > > CHAR16 *DevicePathStr; > > UINTN DevicePathStrSize; > > + UINTN CapFileNameSize; > > + > > + DevicePathStr =3D NULL; > > + CapFileNameSize =3D sizeof(CHAR16); > > > > - DevicePathStr =3D NULL; > > if (FmpDevicePath !=3D NULL) { > > DevicePathStr =3D ConvertDevicePathToText (FmpDevicePath, FALSE, > FALSE); > > } > > if (DevicePathStr !=3D NULL) { > > DevicePathStrSize =3D StrSize(DevicePathStr); > > } else { > > DevicePathStrSize =3D sizeof(CHAR16); > > } > > + > > + if (CapFileName !=3D NULL) { > > + CapFileNameSize =3D StrSize(CapFileName); > > + } > > + > > // > > - // Allocate zero CHAR16 for CapsuleFileName. > > + // Allocate room for CapsuleFileName. > > // > > - CapsuleResultVariableSize =3D > > sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER) + > > sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP) + sizeof(CHAR16) + > > DevicePathStrSize; > > + CapsuleResultVariableSize =3D > > sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER) + > > sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP) + CapFileNameSize + > > DevicePathStrSize; > > + > > CapsuleResultVariable =3D AllocateZeroPool (CapsuleResultVariab= leSize); > > if (CapsuleResultVariable =3D=3D NULL) { > > return EFI_OUT_OF_RESOURCES; > > } > > CapsuleResultVariableHeader =3D (VOID *)CapsuleResultVariable; > > @@ -223,12 +246,17 @@ RecordFmpCapsuleStatusVariable ( > > CapsuleResultVariableFmp =3D (VOID *)(CapsuleResultVariable + > > sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER)); > > CapsuleResultVariableFmp->Version =3D 0x1; > > CapsuleResultVariableFmp->PayloadIndex =3D (UINT8)PayloadIndex; > > CapsuleResultVariableFmp->UpdateImageIndex =3D ImageHeader- > > >UpdateImageIndex; > > CopyGuid (&CapsuleResultVariableFmp->UpdateImageTypeId, > > &ImageHeader->UpdateImageTypeId); > > + > > + if (CapFileName !=3D NULL) { > > + CopyMem((UINT8 *)CapsuleResultVariableFmp + > > sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP), CapFileName, > > CapFileNameSize); > > + } > > + > > if (DevicePathStr !=3D NULL) { > > - CopyMem ((UINT8 *)CapsuleResultVariableFmp + > > sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP) + sizeof(CHAR16), > > DevicePathStr, DevicePathStrSize); > > + CopyMem ((UINT8 *)CapsuleResultVariableFmp + > > sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP) + CapFileNameSize, > > DevicePathStr, DevicePathStrSize); > > FreePool (DevicePathStr); > > DevicePathStr =3D NULL; > > } > > > > Status =3D EFI_SUCCESS; > > @@ -398,10 +426,35 @@ InitCapsuleUpdateVariable ( > > } > > Index++; > > } > > } > > > > +/** > > + Initialize capsule relocation info variable. > > +**/ > > +VOID > > +InitCapsuleRelocationInfo ( > > + VOID > > + ) > > +{ > > + EFI_STATUS Status; > > + EDKII_VARIABLE_LOCK_PROTOCOL *VariableLock; > > + > > + CoDClearCapsuleRelocationInfo(); > > + > > + // > > + // Unlock Capsule On Disk relocation Info variable only when Capsul= e On > > Disk flag is enabled > > + // > > + if (!CoDCheckCapsuleOnDiskFlag()) { > > + Status =3D gBS->LocateProtocol (&gEdkiiVariableLockProtocolGuid, = NULL, > > (VOID **) &VariableLock); > > + if (!EFI_ERROR (Status)) { > > + Status =3D VariableLock->RequestToLock (VariableLock, > > COD_RELOCATION_INFO_VAR_NAME, &gEfiCapsuleVendorGuid); > > + ASSERT_EFI_ERROR (Status); > > + } > > + } > > +} > > + > > /** > > Initialize capsule related variables. > > **/ > > VOID > > InitCapsuleVariable ( > > @@ -409,10 +462,12 @@ InitCapsuleVariable ( > > ) > > { > > InitCapsuleUpdateVariable(); > > InitCapsuleMaxVariable(); > > InitCapsuleLastVariable(); > > + InitCapsuleRelocationInfo(); > > + > > // > > // No need to clear L"Capsule####", because OS/APP should refer > > L"CapsuleLast" > > // to check status and delete them. > > // > > } > > diff --git > > a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf > > b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf > > index 2c93e68700..bf56f4623f 100644 > > --- > a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf > > +++ > > b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf > > @@ -1,11 +1,11 @@ > > ## @file > > # Capsule library instance for DXE_RUNTIME_DRIVER. > > # > > # Capsule library instance for DXE_RUNTIME_DRIVER module types. > > # > > -# Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.=
> > +# Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.=
> > # SPDX-License-Identifier: BSD-2-Clause-Patent > > # > > ## > > > > [Defines] > > @@ -66,8 +66,9 @@ > > gEfiCapsuleReportGuid > > gEfiCapsuleVendorGuid ## SOMETIMES_CONSUMES ## > > Variable:L"CapsuleUpdateData" > > gEfiEndOfDxeEventGroupGuid ## CONSUMES ## Event > > gEfiEventReadyToBootGuid ## CONSUMES ## Event > > gEfiEventVirtualAddressChangeGuid ## CONSUMES ## Event > > + gEdkiiCapsuleOnDiskNameGuid ## SOMETIMES_CONSUMES ## > > GUID > > > > [Depex] > > gEfiVariableWriteArchProtocolGuid > > diff --git a/MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.= c > > b/MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.c > > index 06a1abe16b..39e37cffcd 100644 > > --- a/MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.c > > +++ b/MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.c > > @@ -1,9 +1,9 @@ > > /** @file > > Null Dxe Capsule Library instance does nothing and returns unsuppor= t > > status. > > > > -Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved. > > +Copyright (c) 2007 - 2019, Intel Corporation. All rights reserved. > > SPDX-License-Identifier: BSD-2-Clause-Patent > > > > **/ > > #include > > #include > > @@ -83,5 +83,88 @@ ProcessCapsules ( > > ) > > { > > return EFI_UNSUPPORTED; > > } > > > > + > > +/** > > + This routine is called to check if CapsuleOnDisk flag in OsIndicati= ons > > Variable > > + is enabled. > > + > > + @retval TRUE Flag is enabled > > + @retval FALSE Flag is not enabled > > + > > +**/ > > +BOOLEAN > > +EFIAPI > > +CoDCheckCapsuleOnDiskFlag( > > + VOID > > + ) > > +{ > > + return FALSE; > > +} > > + > > +/** > > + This routine is called to clear CapsuleOnDisk flags including OsInd= ications > > and BootNext variable. > > + > > + @retval EFI_SUCCESS All Capsule On Disk flags are cleared > > + > > +**/ > > +EFI_STATUS > > +EFIAPI > > +CoDClearCapsuleOnDiskFlag( > > + VOID > > + ) > > +{ > > + return EFI_UNSUPPORTED; > > +} > > + > > +/** > > + Relocate Capsule on Disk from EFI system partition. > > + > > + Two solution to deliver Capsule On Disk: > > + Solution A: If PcdCapsuleInRamSupport is enabled, relocate Capsule = On > > Disk to memory and call UpdateCapsule(). > > + Solution B: If PcdCapsuleInRamSupport is disabled, relocate Capsule= On > > Disk to a platform-specific NV storage > > + device with BlockIo protocol. > > + > > + Device enumeration like USB costs time, user can input MaxRetry to = tell > > function to retry. > > + Function will stall 100ms between each retry. > > + > > + Side Effects: > > + Capsule Delivery Supported Flag in OsIndication variable and Boot= Next > > variable will be cleared. > > + Solution B: Content corruption. Block IO write directly touches l= ow level > > write. Orignal partitions, file > > + systems of the relocation device will be corrupted. > > + > > + @param[in] MaxRetry Max Connection Retry. Stall 100m= s > between > > each connection try to ensure > > + devices like USB can get enumera= ted. > > + > > + @retval EFI_SUCCESS Capsule on Disk images are sucessfully reloca= ted. > > + > > +**/ > > +EFI_STATUS > > +EFIAPI > > +CoDRelocateCapsule( > > + UINTN MaxRetry > > + ) > > +{ > > + return EFI_UNSUPPORTED; > > +} > > + > > +/** > > + Remove the temp file from the root of EFI System Partition. > > + Device enumeration like USB costs time, user can input MaxRetry to = tell > > function to retry. > > + Function will stall 100ms between each retry. > > + > > + @param[in] MaxRetry Max Connection Retry. Stall 100m= s > between > > each connection try to ensure > > + devices like USB can get enumera= ted. > > + > > + @retval EFI_SUCCESS Remove the temp file successfully. > > + > > +**/ > > +EFI_STATUS > > +EFIAPI > > +CoDRemoveTempFile ( > > + UINTN MaxRetry > > + ) > > +{ > > + return EFI_UNSUPPORTED; > > +} > > -- > > 2.16.2.windows.1 > > > > > >=20