Sunny, I guess you may have misunderstanding about the EndOfDxe signal time. This event is not signaled immediately before calling Bds->Entry(). This event is signaled by platform (in PlatformBootManagerBeforeConsole). So it means all the PlatformRecovery#### variables need to be created in core (before PlatformBootManagerBeforeConsole()) or in PlatformBootManagerBeforeConsole().
I agree with your other comments. Regards, Ray -----Original Message----- From: edk2-devel [mailto:edk2-devel-boun...@lists.01.org] On Behalf Of Wang, Sunny (HPS SW) Sent: Thursday, November 5, 2015 9:17 PM To: Ni, Ruiyu <ruiyu...@intel.com>; edk2-devel@lists.01.org Cc: Dong, Eric <eric.d...@intel.com> Subject: Re: [edk2] [Patch 07/11] MdeModulePkg: Add Platform recovery support Hi Ray, I made four comments in this patch. You can search "[Sunny]" to find them out. Regards, Sunny Wang -----Original Message----- From: edk2-devel [mailto:edk2-devel-boun...@lists.01.org] On Behalf Of Ruiyu Ni Sent: Monday, November 02, 2015 7:34 PM To: edk2-devel@lists.01.org Cc: Ruiyu Ni; Eric Dong Subject: [edk2] [Patch 07/11] MdeModulePkg: Add Platform recovery support Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu...@intel.com> Cc: Eric Dong <eric.d...@intel.com> --- MdeModulePkg/Include/Library/UefiBootManagerLib.h | 1 + .../Library/UefiBootManagerLib/BmLoadOption.c | 130 ++++++++++++++++++--- .../Library/UefiBootManagerLib/InternalBm.h | 3 +- .../UefiBootManagerLib/UefiBootManagerLib.inf | 1 + 4 files changed, 118 insertions(+), 17 deletions(-) diff --git a/MdeModulePkg/Include/Library/UefiBootManagerLib.h b/MdeModulePkg/Include/Library/UefiBootManagerLib.h index 5538d90..1b04a8c 100644 --- a/MdeModulePkg/Include/Library/UefiBootManagerLib.h +++ b/MdeModulePkg/Include/Library/UefiBootManagerLib.h @@ -30,6 +30,7 @@ typedef enum { LoadOptionTypeDriver, LoadOptionTypeSysPrep, LoadOptionTypeBoot, + LoadOptionTypePlatformRecovery, LoadOptionTypeMax } EFI_BOOT_MANAGER_LOAD_OPTION_TYPE; diff --git a/MdeModulePkg/Library/UefiBootManagerLib/BmLoadOption.c b/MdeModulePkg/Library/UefiBootManagerLib/BmLoadOption.c index fbd7830..454fe20 100644 --- a/MdeModulePkg/Library/UefiBootManagerLib/BmLoadOption.c +++ b/MdeModulePkg/Library/UefiBootManagerLib/BmLoadOption.c @@ -18,14 +18,16 @@ GLOBAL_REMOVE_IF_UNREFERENCED CHAR16 *mBmLoadOptionName[] = { L"Driver", L"SysPrep", - L"Boot" + L"Boot", + L"PlatformRecovery" }; GLOBAL_REMOVE_IF_UNREFERENCED CHAR16 *mBmLoadOptionOrderName[] = { EFI_DRIVER_ORDER_VARIABLE_NAME, EFI_SYS_PREP_ORDER_VARIABLE_NAME, - EFI_BOOT_ORDER_VARIABLE_NAME + EFI_BOOT_ORDER_VARIABLE_NAME, + NULL // PlatformRecovery#### doesn't have associated *Order + variable }; /** @@ -153,8 +155,9 @@ BmGetFreeOptionNumber ( } /** - Create the Boot####, Driver####, SysPrep####, variable from the load option. - + Create the Boot####, Driver####, SysPrep####, PlatformRecovery#### + variable from the load option. + @param LoadOption Pointer to the load option. @retval EFI_SUCCESS The variable was created. @@ -166,12 +169,14 @@ EfiBootManagerLoadOptionToVariable ( IN CONST EFI_BOOT_MANAGER_LOAD_OPTION *Option ) { + EFI_STATUS Status; UINTN VariableSize; UINT8 *Variable; UINT8 *Ptr; CHAR16 OptionName[BM_OPTION_NAME_LEN]; CHAR16 *Description; CHAR16 NullChar; + EDKII_VARIABLE_LOCK_PROTOCOL *VariableLock; UINT32 VariableAttributes; if ((Option->OptionNumber == LoadOptionNumberUnassigned) || @@ -232,6 +237,17 @@ structure. UnicodeSPrint (OptionName, sizeof (OptionName), L"%s%04x", mBmLoadOptionName[Option->OptionType], Option->OptionNumber); VariableAttributes = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE; + if (Option->OptionType == LoadOptionTypePlatformRecovery) { + // + // Lock the PlatformRecovery#### + // + Status = gBS->LocateProtocol (&gEdkiiVariableLockProtocolGuid, NULL, (VOID **) &VariableLock); + if (!EFI_ERROR (Status)) { + Status = VariableLock->RequestToLock (VariableLock, OptionName, &gEfiGlobalVariableGuid); + ASSERT_EFI_ERROR (Status); + } + VariableAttributes = EFI_VARIABLE_BOOTSERVICE_ACCESS | + EFI_VARIABLE_RUNTIME_ACCESS; } [Sunny] Should we lock the variable after calling SetVariable? It seems the locked variable can't be set. [Sunny] I saw the UEFI spec said that PlatformRecovery#### variables are only modified by firmware and are read-only to the OS. However, it seems the locked variable would possibly become read-only after Signaling end of DXE event (at the beginning of BDS). If my understanding is correct, that means the firmware will have NO chance to modify the created PlatformRecovery#### variable in BDS once it has been locked. Is it a problem or I have misunderstanding on this? return gRT->SetVariable ( OptionName, @@ -548,6 +564,7 @@ EfiBootManagerDeleteLoadOptionVariable ( UINTN OptionOrderSize; EFI_STATUS Status; UINTN Index; + CHAR16 OptionName[BM_OPTION_NAME_LEN]; if (((UINT32) OptionType >= LoadOptionTypeMax) || (OptionNumber >= LoadOptionNumberMax)) { return EFI_INVALID_PARAMETER; @@ -579,6 +596,19 @@ EfiBootManagerDeleteLoadOptionVariable ( if (OptionOrder != NULL) { FreePool (OptionOrder); } + } else { [Sunny] I would like to make sure that changing to different behavior for the unsupported OptionType is intended. The original code would directly return EFI_NOT_FOUND and do nothing for the unsupported OptionType. However, in this patch, the unsupported OptionType will cause ASSERT and would possibly still run this code block to SetVariable. Could you check whether this is an expected behavior? Is it change to "} else if (OptionType == LoadOptionTypePlatformRecovery) {" instead of "} else {" and "ASSERT (....." + ASSERT (OptionType == LoadOptionTypePlatformRecovery); + // + // PlatformRecovery#### doesn't have assiciated PlatformRecoveryOrder, remove the PlatformRecovery#### itself. + // + UnicodeSPrint (OptionName, sizeof (OptionName), L"%s%04x", mBmLoadOptionName[OptionType], OptionNumber); + Status = gRT->SetVariable ( + OptionName, + &gEfiGlobalVariableGuid, + 0, + 0, + NULL + ); } return Status; @@ -675,7 +705,8 @@ BmStrSizeEx ( } /** - Validate the Boot####, Driver####, SysPrep#### variable (VendorGuid/Name) + Validate the Boot####, Driver####, SysPrep#### and + PlatformRecovery#### variable (VendorGuid/Name) @param Variable The variable data. @param VariableSize The variable size. @@ -918,6 +949,62 @@ EfiBootManagerVariableToLoadOption ( return EfiBootManagerVariableToLoadOptionEx (VariableName, &gEfiGlobalVariableGuid, Option); } +typedef struct { + EFI_BOOT_MANAGER_LOAD_OPTION_TYPE OptionType; + EFI_GUID *Guid; + EFI_BOOT_MANAGER_LOAD_OPTION *Options; + UINTN OptionCount; +} BM_COLLECT_LOAD_OPTIONS_PARAM; + +/** + Visitor function to collect the Platform Recovery load options or OS +Recovery + load options from NV storage. + + @param Name Variable name. + @param Guid Variable GUID. + @param Context The same context passed to BmForEachVariable. +**/ +VOID +BmCollectLoadOptions ( + IN CHAR16 *Name, + IN EFI_GUID *Guid, + IN VOID *Context + ) +{ + EFI_STATUS Status; + EFI_BOOT_MANAGER_LOAD_OPTION_TYPE OptionType; + UINT16 OptionNumber; + EFI_BOOT_MANAGER_LOAD_OPTION Option; + UINTN Index; + BM_COLLECT_LOAD_OPTIONS_PARAM *Param; + + Param = (BM_COLLECT_LOAD_OPTIONS_PARAM *) Context; + + if (CompareGuid (Guid, Param->Guid) && ( + Param->OptionType == LoadOptionTypePlatformRecovery && + BmIsValidLoadOptionVariableName (Name, &OptionType, &OptionNumber) && + OptionType == LoadOptionTypePlatformRecovery + )) { + Status = EfiBootManagerVariableToLoadOptionEx (Name, Guid, &Option); + if (!EFI_ERROR (Status)) { + for (Index = 0; Index < Param->OptionCount; Index++) { + if (Param->Options[Index].OptionNumber > Option.OptionNumber) { + break; + } + } + Param->Options = ReallocatePool ( + Param->OptionCount * sizeof (EFI_BOOT_MANAGER_LOAD_OPTION), + (Param->OptionCount + 1) * sizeof (EFI_BOOT_MANAGER_LOAD_OPTION), + Param->Options + ); + ASSERT (Param->Options != NULL); + CopyMem (&Param->Options[Index + 1], &Param->Options[Index], (Param->OptionCount - Index) * sizeof (EFI_BOOT_MANAGER_LOAD_OPTION)); + CopyMem (&Param->Options[Index], &Option, sizeof (EFI_BOOT_MANAGER_LOAD_OPTION)); + Param->OptionCount++; + } + } +} + /** Returns an array of load options based on the EFI variable L"BootOrder"/L"DriverOrder" and the L"Boot####"/L"Driver####" variables impled by it. @@ -937,16 +1024,18 @@ EfiBootManagerGetLoadOptions ( IN EFI_BOOT_MANAGER_LOAD_OPTION_TYPE LoadOptionType ) { - EFI_STATUS Status; - UINT16 *OptionOrder; - UINTN OptionOrderSize; - UINTN Index; - UINTN OptionIndex; - EFI_BOOT_MANAGER_LOAD_OPTION *Options; - CHAR16 OptionName[BM_OPTION_NAME_LEN]; - UINT16 OptionNumber; + EFI_STATUS Status; + UINT16 *OptionOrder; + UINTN OptionOrderSize; + UINTN Index; + UINTN OptionIndex; + EFI_BOOT_MANAGER_LOAD_OPTION *Options; + CHAR16 OptionName[BM_OPTION_NAME_LEN]; + UINT16 OptionNumber; + BM_COLLECT_LOAD_OPTIONS_PARAM Param; *OptionCount = 0; + Options = NULL; if (LoadOptionType == LoadOptionTypeDriver || LoadOptionType == LoadOptionTypeSysPrep || LoadOptionType == LoadOptionTypeBoot) { // @@ -987,8 +1076,16 @@ EfiBootManagerGetLoadOptions ( *OptionCount = OptionIndex; } - } else { - return NULL; + } else if (LoadOptionType == LoadOptionTypePlatformRecovery) { + Param.OptionType = LoadOptionTypePlatformRecovery; + Param.Options = NULL; + Param.OptionCount = 0; + Param.Guid = &gEfiGlobalVariableGuid; + + BmForEachVariable (BmCollectLoadOptions, (VOID *) &Param); + + *OptionCount = Param.OptionCount; + Options = Param.Options; } return Options; @@ -1116,7 +1213,8 @@ BmIsLoadOptionPeHeaderValid ( if ((Type == LoadOptionTypeDriver && Subsystem == EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER) || (Type == LoadOptionTypeDriver && Subsystem == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) || (Type == LoadOptionTypeSysPrep && Subsystem == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION) || - (Type == LoadOptionTypeBoot && Subsystem == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION) + (Type == LoadOptionTypeBoot && Subsystem == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION) || + (Type == LoadOptionTypePlatformRecovery && Subsystem == + EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION) ) { return TRUE; } diff --git a/MdeModulePkg/Library/UefiBootManagerLib/InternalBm.h b/MdeModulePkg/Library/UefiBootManagerLib/InternalBm.h index 7f52b13..3fc9cc7 100644 --- a/MdeModulePkg/Library/UefiBootManagerLib/InternalBm.h +++ b/MdeModulePkg/Library/UefiBootManagerLib/InternalBm.h @@ -41,6 +41,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include <Protocol/BootLogo.h> #include <Protocol/DriverHealth.h> #include <Protocol/FormBrowser2.h> +#include <Protocol/VariableLock.h> #include <Guid/ZeroGuid.h> #include <Guid/MemoryTypeInformation.h> @@ -101,7 +102,7 @@ CHAR16 * IN EFI_HANDLE Handle ); [Sunny] Just a suggestion. Is it a good idea to rename it to BM_OPTION_NAME_MAX_LEN or add comment here to explain why we use PlatformRecovery#### to get BM_OPTION_NAME_LEN (because it is the option variable with longest name)? -#define BM_OPTION_NAME_LEN sizeof ("SysPrep####") +#define BM_OPTION_NAME_LEN sizeof ("PlatformRecovery####") extern CHAR16 *mBmLoadOptionName[]; /** diff --git a/MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf b/MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf index a2c6441..f1f6246 100644 --- a/MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf +++ b/MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf @@ -101,6 +101,7 @@ gEfiDevicePathProtocolGuid ## CONSUMES gEfiBootLogoProtocolGuid ## CONSUMES gEfiSimpleTextInputExProtocolGuid ## CONSUMES + gEdkiiVariableLockProtocolGuid ## CONSUMES gEfiGraphicsOutputProtocolGuid ## SOMETIMES_CONSUMES gEfiUsbIoProtocolGuid ## SOMETIMES_CONSUMES gEfiDiskInfoProtocolGuid ## SOMETIMES_CONSUMES -- 1.9.5.msysgit.1 _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel