X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=MdeModulePkg%2FLibrary%2FUefiBootManagerLib%2FBmLoadOption.c;h=6f705bd4673f12a74919248cc5a229ace880e4d5;hp=630307ed031778dacd78897df4f98e358609672f;hb=3fc46b79d82922f33af29bf6c9d0de0062ebda12;hpb=067ed98a734eabd311b8c2c8ebd48b67e0242afa diff --git a/MdeModulePkg/Library/UefiBootManagerLib/BmLoadOption.c b/MdeModulePkg/Library/UefiBootManagerLib/BmLoadOption.c index 630307ed03..6f705bd467 100644 --- a/MdeModulePkg/Library/UefiBootManagerLib/BmLoadOption.c +++ b/MdeModulePkg/Library/UefiBootManagerLib/BmLoadOption.c @@ -1,7 +1,8 @@ /** @file Load option library functions which relate with creating and processing load options. -Copyright (c) 2011 - 2015, Intel Corporation. All rights reserved.
+Copyright (c) 2011 - 2016, Intel Corporation. All rights reserved.
+(C) Copyright 2015-2016 Hewlett Packard Enterprise Development LP
This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License which accompanies this distribution. The full text of the license may be found at @@ -18,14 +19,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 }; /** @@ -36,7 +39,7 @@ GLOBAL_REMOVE_IF_UNREFERENCED **/ VOID BmForEachVariable ( - VARIABLE_VISITOR Visitor, + BM_VARIABLE_VISITOR Visitor, VOID *Context ) { @@ -100,6 +103,8 @@ BmGetFreeOptionNumber ( LoadOptionType == LoadOptionTypeSysPrep); GetEfiGlobalVariable2 (mBmLoadOptionOrderName[LoadOptionType], (VOID **) &OptionOrder, &OptionOrderSize); + ASSERT ((OptionOrder != NULL && OptionOrderSize != 0) || (OptionOrder == NULL && OptionOrderSize == 0)); + BootNext = NULL; if (LoadOptionType == LoadOptionTypeBoot) { GetEfiGlobalVariable2 (L"BootNext", (VOID**) &BootNext, NULL); @@ -151,8 +156,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. @@ -164,12 +170,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) || @@ -230,6 +238,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; + } return gRT->SetVariable ( OptionName, @@ -268,6 +287,7 @@ BmAddOptionNumberToOrderVariable ( // Update the option order variable // GetEfiGlobalVariable2 (OptionOrderName, (VOID **) &OptionOrder, &OptionOrderSize); + ASSERT ((OptionOrder != NULL && OptionOrderSize != 0) || (OptionOrder == NULL && OptionOrderSize == 0)); Status = EFI_SUCCESS; for (Index = 0; Index < OptionOrderSize / sizeof (UINT16); Index++) { @@ -501,7 +521,8 @@ EfiBootManagerInitializeLoadOption ( @retval 0 ~ Count-1 The index of the Key in the Array. **/ INTN -BmFindLoadOption ( +EFIAPI +EfiBootManagerFindLoadOption ( IN CONST EFI_BOOT_MANAGER_LOAD_OPTION *Key, IN CONST EFI_BOOT_MANAGER_LOAD_OPTION *Array, IN UINTN Count @@ -543,31 +564,32 @@ EfiBootManagerDeleteLoadOptionVariable ( { UINT16 *OptionOrder; UINTN OptionOrderSize; - EFI_STATUS Status; UINTN Index; + CHAR16 OptionName[BM_OPTION_NAME_LEN]; if (((UINT32) OptionType >= LoadOptionTypeMax) || (OptionNumber >= LoadOptionNumberMax)) { return EFI_INVALID_PARAMETER; } - Status = EFI_NOT_FOUND; - if (OptionType == LoadOptionTypeDriver || OptionType == LoadOptionTypeSysPrep || OptionType == LoadOptionTypeBoot) { // - // If the associated *Order exists, just remove the reference in *Order. + // If the associated *Order exists, firstly remove the reference in *Order for + // Driver####, SysPrep#### and Boot####. // - GetEfiGlobalVariable2 (mBmLoadOptionOrderName[OptionType], &OptionOrder, &OptionOrderSize); + GetEfiGlobalVariable2 (mBmLoadOptionOrderName[OptionType], (VOID **) &OptionOrder, &OptionOrderSize); + ASSERT ((OptionOrder != NULL && OptionOrderSize != 0) || (OptionOrder == NULL && OptionOrderSize == 0)); + for (Index = 0; Index < OptionOrderSize / sizeof (UINT16); Index++) { if (OptionOrder[Index] == OptionNumber) { OptionOrderSize -= sizeof (UINT16); CopyMem (&OptionOrder[Index], &OptionOrder[Index + 1], OptionOrderSize - Index * sizeof (UINT16)); - Status = gRT->SetVariable ( - mBmLoadOptionOrderName[OptionType], - &gEfiGlobalVariableGuid, - EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, - OptionOrderSize, - OptionOrder - ); + gRT->SetVariable ( + mBmLoadOptionOrderName[OptionType], + &gEfiGlobalVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, + OptionOrderSize, + OptionOrder + ); break; } } @@ -576,30 +598,17 @@ EfiBootManagerDeleteLoadOptionVariable ( } } - return Status; -} - -/** - Convert a single character to number. - It assumes the input Char is in the scope of L'0' ~ L'9' and L'A' ~ L'F' - - @param Char The input char which need to convert to int. -**/ -UINTN -BmCharToUint ( - IN CHAR16 Char - ) -{ - if ((Char >= L'0') && (Char <= L'9')) { - return (UINTN) (Char - L'0'); - } - - if ((Char >= L'A') && (Char <= L'F')) { - return (UINTN) (Char - L'A' + 0xA); - } - - ASSERT (FALSE); - return (UINTN) -1; + // + // Remove the Driver####, SysPrep####, Boot#### or PlatformRecovery#### itself. + // + UnicodeSPrint (OptionName, sizeof (OptionName), L"%s%04x", mBmLoadOptionName[OptionType], OptionNumber); + return gRT->SetVariable ( + OptionName, + &gEfiGlobalVariableGuid, + 0, + 0, + NULL + ); } /** @@ -693,7 +702,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. @@ -765,23 +775,28 @@ BmValidateOption ( @retval FALSE The variable name is NOT valid. **/ BOOLEAN -BmIsValidLoadOptionVariableName ( +EFIAPI +EfiBootManagerIsValidLoadOptionVariableName ( IN CHAR16 *VariableName, - OUT EFI_BOOT_MANAGER_LOAD_OPTION_TYPE *OptionType, - OUT UINT16 *OptionNumber + OUT EFI_BOOT_MANAGER_LOAD_OPTION_TYPE *OptionType OPTIONAL, + OUT UINT16 *OptionNumber OPTIONAL ) { UINTN VariableNameLen; UINTN Index; UINTN Uint; + if (VariableName == NULL) { + return FALSE; + } + VariableNameLen = StrLen (VariableName); if (VariableNameLen <= 4) { return FALSE; } - for (Index = 0; Index < sizeof (mBmLoadOptionName) / sizeof (mBmLoadOptionName[0]); Index++) { + for (Index = 0; Index < ARRAY_SIZE (mBmLoadOptionName); Index++) { if ((VariableNameLen - 4 == StrLen (mBmLoadOptionName[Index])) && (StrnCmp (VariableName, mBmLoadOptionName[Index], VariableNameLen - 4) == 0) ) { @@ -789,18 +804,23 @@ BmIsValidLoadOptionVariableName ( } } - if (Index == sizeof (mBmLoadOptionName) / sizeof (mBmLoadOptionName[0])) { + if (Index == ARRAY_SIZE (mBmLoadOptionName)) { return FALSE; } - *OptionType = (EFI_BOOT_MANAGER_LOAD_OPTION_TYPE) Index; - *OptionNumber = 0; - for (Index = VariableNameLen - 4; Index < VariableNameLen; Index++) { - Uint = BmCharToUint (VariableName[Index]); - if (Uint == -1) { - break; - } else { - *OptionNumber = (UINT16) Uint + *OptionNumber * 0x10; + if (OptionType != NULL) { + *OptionType = (EFI_BOOT_MANAGER_LOAD_OPTION_TYPE) Index; + } + + if (OptionNumber != NULL) { + *OptionNumber = 0; + for (Index = VariableNameLen - 4; Index < VariableNameLen; Index++) { + Uint = BmCharToUint (VariableName[Index]); + if (Uint == -1) { + break; + } else { + *OptionNumber = (UINT16) Uint + *OptionNumber * 0x10; + } } } @@ -843,7 +863,7 @@ EfiBootManagerVariableToLoadOptionEx ( return EFI_INVALID_PARAMETER; } - if (!BmIsValidLoadOptionVariableName (VariableName, &OptionType, &OptionNumber)) { + if (!EfiBootManagerIsValidLoadOptionVariableName (VariableName, &OptionType, &OptionNumber)) { return EFI_INVALID_PARAMETER; } @@ -936,6 +956,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 && + EfiBootManagerIsValidLoadOptionVariableName (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. @@ -955,16 +1031,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) { // @@ -1005,8 +1083,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; @@ -1134,7 +1220,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; } @@ -1190,11 +1277,12 @@ EfiBootManagerProcessLoadOption ( // Load and start the load option. // DEBUG (( - DEBUG_INFO | DEBUG_LOAD, "Process Load Option (%s%04x) ...\n", - mBmLoadOptionName[LoadOption->OptionType], LoadOption->OptionNumber + DEBUG_INFO | DEBUG_LOAD, "Process %s%04x (%s) ...\n", + mBmLoadOptionName[LoadOption->OptionType], LoadOption->OptionNumber, + LoadOption->Description )); ImageHandle = NULL; - FileBuffer = BmGetLoadOptionBuffer (LoadOption->FilePath, &FilePath, &FileSize); + FileBuffer = EfiBootManagerGetLoadOptionBuffer (LoadOption->FilePath, &FilePath, &FileSize); DEBUG_CODE ( if (FileBuffer != NULL && CompareMem (LoadOption->FilePath, FilePath, GetDevicePathSize (FilePath)) != 0) { DEBUG ((EFI_D_INFO, "[Bds] DevicePath expand: ")); @@ -1234,7 +1322,7 @@ EfiBootManagerProcessLoadOption ( LoadOption->Status = gBS->StartImage (ImageHandle, &LoadOption->ExitDataSize, &LoadOption->ExitData); DEBUG (( - DEBUG_INFO | DEBUG_LOAD, "Load Option (%s%04x) Return Status = %r\n", + DEBUG_INFO | DEBUG_LOAD, "%s%04x Return Status = %r\n", mBmLoadOptionName[LoadOption->OptionType], LoadOption->OptionNumber, LoadOption->Status ));