OvmfPkg/QemuNewBootOrderLib: Build with UefiBootManagerLib

NOTE: SetBootOrderFromQemu() interface is not changed.
But when the old IntelFrameworkModulePkg/BDS is no longer used in
OVMF and ArmVirtPkg, additional patch will be submitted to change
this interface to remove parameter BootOptionList.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Tested-by: Laszlo Ersek <lersek@redhat.com>
This commit is contained in:
Ruiyu Ni
2016-04-20 15:27:48 +08:00
parent 6b40e66a48
commit d27ec22d11
2 changed files with 114 additions and 51 deletions

View File

@ -2,7 +2,7 @@
Rewrite the BootOrder NvVar based on QEMU's "bootorder" fw_cfg file. Rewrite the BootOrder NvVar based on QEMU's "bootorder" fw_cfg file.
Copyright (C) 2012 - 2014, Red Hat, Inc. Copyright (C) 2012 - 2014, Red Hat, Inc.
Copyright (c) 2013, Intel Corporation. All rights reserved.<BR> Copyright (c) 2013 - 2016, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials are licensed and made available This program and the accompanying materials are licensed and made available
under the terms and conditions of the BSD License which accompanies this under the terms and conditions of the BSD License which accompanies this
@ -16,7 +16,7 @@
#include <Library/QemuFwCfgLib.h> #include <Library/QemuFwCfgLib.h>
#include <Library/DebugLib.h> #include <Library/DebugLib.h>
#include <Library/MemoryAllocationLib.h> #include <Library/MemoryAllocationLib.h>
#include <Library/GenericBdsLib.h> #include <Library/UefiBootManagerLib.h>
#include <Library/UefiBootServicesTableLib.h> #include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiRuntimeServicesTableLib.h> #include <Library/UefiRuntimeServicesTableLib.h>
#include <Library/BaseLib.h> #include <Library/BaseLib.h>
@ -253,8 +253,10 @@ typedef struct {
LOAD_OPTION_ACTIVE attribute. LOAD_OPTION_ACTIVE attribute.
**/ **/
typedef struct { typedef struct {
CONST BDS_COMMON_OPTION *BootOption; // reference only, no ownership CONST EFI_BOOT_MANAGER_LOAD_OPTION *BootOption; // reference only, no
BOOLEAN Appended; // has been added to a BOOT_ORDER? // ownership
BOOLEAN Appended; // has been added to a
// BOOT_ORDER?
} ACTIVE_OPTION; } ACTIVE_OPTION;
@ -300,7 +302,7 @@ BootOrderAppend (
} }
BootOrder->Data[BootOrder->Produced++] = BootOrder->Data[BootOrder->Produced++] =
ActiveOption->BootOption->BootCurrent; (UINT16) ActiveOption->BootOption->OptionNumber;
ActiveOption->Appended = TRUE; ActiveOption->Appended = TRUE;
return RETURN_SUCCESS; return RETURN_SUCCESS;
} }
@ -308,22 +310,25 @@ BootOrderAppend (
/** /**
Create an array of ACTIVE_OPTION elements for a boot option list. Create an array of ACTIVE_OPTION elements for a boot option array.
@param[in] BootOptionList A boot option list, created with @param[in] BootOptions A boot option array, created with
BdsLibEnumerateAllBootOption(). EfiBootManagerRefreshAllBootOption () and
EfiBootManagerGetLoadOptions ().
@param[out] ActiveOption Pointer to the first element in the new array. @param[in] BootOptionCount The number of elements in BootOptions.
The caller is responsible for freeing the array
with FreePool() after use.
@param[out] Count Number of elements in the new array. @param[out] ActiveOption Pointer to the first element in the new array.
The caller is responsible for freeing the array
with FreePool() after use.
@param[out] Count Number of elements in the new array.
@retval RETURN_SUCCESS The ActiveOption array has been created. @retval RETURN_SUCCESS The ActiveOption array has been created.
@retval RETURN_NOT_FOUND No active entry has been found in @retval RETURN_NOT_FOUND No active entry has been found in
BootOptionList. BootOptions.
@retval RETURN_OUT_OF_RESOURCES Memory allocation failed. @retval RETURN_OUT_OF_RESOURCES Memory allocation failed.
@ -331,11 +336,13 @@ BootOrderAppend (
STATIC STATIC
RETURN_STATUS RETURN_STATUS
CollectActiveOptions ( CollectActiveOptions (
IN CONST LIST_ENTRY *BootOptionList, IN CONST EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions,
OUT ACTIVE_OPTION **ActiveOption, IN UINTN BootOptionCount,
OUT UINTN *Count OUT ACTIVE_OPTION **ActiveOption,
OUT UINTN *Count
) )
{ {
UINTN Index;
UINTN ScanMode; UINTN ScanMode;
*ActiveOption = NULL; *ActiveOption = NULL;
@ -346,22 +353,15 @@ CollectActiveOptions (
// - store links to active entries. // - store links to active entries.
// //
for (ScanMode = 0; ScanMode < 2; ++ScanMode) { for (ScanMode = 0; ScanMode < 2; ++ScanMode) {
CONST LIST_ENTRY *Link;
Link = BootOptionList->ForwardLink;
*Count = 0; *Count = 0;
while (Link != BootOptionList) { for (Index = 0; Index < BootOptionCount; Index++) {
CONST BDS_COMMON_OPTION *Current; if ((BootOptions[Index].Attributes & LOAD_OPTION_ACTIVE) != 0) {
Current = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE);
if (IS_LOAD_OPTION_TYPE (Current->Attribute, LOAD_OPTION_ACTIVE)) {
if (ScanMode == 1) { if (ScanMode == 1) {
(*ActiveOption)[*Count].BootOption = Current; (*ActiveOption)[*Count].BootOption = &BootOptions[Index];
(*ActiveOption)[*Count].Appended = FALSE; (*ActiveOption)[*Count].Appended = FALSE;
} }
++*Count; ++*Count;
} }
Link = Link->ForwardLink;
} }
if (ScanMode == 0) { if (ScanMode == 0) {
@ -1437,11 +1437,17 @@ BOOLEAN
Match ( Match (
IN CONST CHAR16 *Translated, IN CONST CHAR16 *Translated,
IN UINTN TranslatedLength, IN UINTN TranslatedLength,
IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
) )
{ {
CHAR16 *Converted; CHAR16 *Converted;
BOOLEAN Result; BOOLEAN Result;
VOID *FileBuffer;
UINTN FileSize;
EFI_DEVICE_PATH_PROTOCOL *AbsDevicePath;
CHAR16 *AbsConverted;
BOOLEAN Shortform;
EFI_DEVICE_PATH_PROTOCOL *Node;
Converted = ConvertDevicePathToText ( Converted = ConvertDevicePathToText (
DevicePath, DevicePath,
@ -1452,24 +1458,57 @@ Match (
return FALSE; return FALSE;
} }
//
// Attempt to expand any relative UEFI device path starting with HD() to an
// absolute device path first. The logic imitates BdsLibBootViaBootOption().
// We don't have to free the absolute device path,
// BdsExpandPartitionPartialDevicePathToFull() has internal caching.
//
Result = FALSE; Result = FALSE;
if (DevicePathType (DevicePath) == MEDIA_DEVICE_PATH && Shortform = FALSE;
DevicePathSubType (DevicePath) == MEDIA_HARDDRIVE_DP) { //
EFI_DEVICE_PATH_PROTOCOL *AbsDevicePath; // Expand the short-form device path to full device path
CHAR16 *AbsConverted; //
if ((DevicePathType (DevicePath) == MEDIA_DEVICE_PATH) &&
(DevicePathSubType (DevicePath) == MEDIA_HARDDRIVE_DP)) {
//
// Harddrive shortform device path
//
Shortform = TRUE;
} else if ((DevicePathType (DevicePath) == MEDIA_DEVICE_PATH) &&
(DevicePathSubType (DevicePath) == MEDIA_FILEPATH_DP)) {
//
// File-path shortform device path
//
Shortform = TRUE;
} else if ((DevicePathType (DevicePath) == MESSAGING_DEVICE_PATH) &&
(DevicePathSubType (DevicePath) == MSG_URI_DP)) {
//
// URI shortform device path
//
Shortform = TRUE;
} else {
for ( Node = DevicePath
; !IsDevicePathEnd (Node)
; Node = NextDevicePathNode (Node)
) {
if ((DevicePathType (Node) == MESSAGING_DEVICE_PATH) &&
((DevicePathSubType (Node) == MSG_USB_CLASS_DP) ||
(DevicePathSubType (Node) == MSG_USB_WWID_DP))) {
Shortform = TRUE;
break;
}
}
}
AbsDevicePath = BdsExpandPartitionPartialDevicePathToFull ( //
(HARDDRIVE_DEVICE_PATH *) DevicePath); // Attempt to expand any relative UEFI device path to
if (AbsDevicePath == NULL) { // an absolute device path first.
//
if (Shortform) {
FileBuffer = EfiBootManagerGetLoadOptionBuffer (
DevicePath, &AbsDevicePath, &FileSize
);
if (FileBuffer == NULL) {
goto Exit; goto Exit;
} }
FreePool (FileBuffer);
AbsConverted = ConvertDevicePathToText (AbsDevicePath, FALSE, FALSE); AbsConverted = ConvertDevicePathToText (AbsDevicePath, FALSE, FALSE);
FreePool (AbsDevicePath);
if (AbsConverted == NULL) { if (AbsConverted == NULL) {
goto Exit; goto Exit;
} }
@ -1538,11 +1577,11 @@ BootOrderComplete (
Idx = 0; Idx = 0;
while (!RETURN_ERROR (Status) && Idx < ActiveCount) { while (!RETURN_ERROR (Status) && Idx < ActiveCount) {
if (!ActiveOption[Idx].Appended) { if (!ActiveOption[Idx].Appended) {
CONST BDS_COMMON_OPTION *Current; CONST EFI_BOOT_MANAGER_LOAD_OPTION *Current;
CONST EFI_DEVICE_PATH_PROTOCOL *FirstNode; CONST EFI_DEVICE_PATH_PROTOCOL *FirstNode;
Current = ActiveOption[Idx].BootOption; Current = ActiveOption[Idx].BootOption;
FirstNode = Current->DevicePath; FirstNode = Current->FilePath;
if (FirstNode != NULL) { if (FirstNode != NULL) {
CHAR16 *Converted; CHAR16 *Converted;
STATIC CHAR16 ConvFallBack[] = L"<unable to convert>"; STATIC CHAR16 ConvFallBack[] = L"<unable to convert>";
@ -1635,7 +1674,7 @@ PruneBootVariables (
CHAR16 VariableName[9]; CHAR16 VariableName[9];
UnicodeSPrintAsciiFormat (VariableName, sizeof VariableName, "Boot%04x", UnicodeSPrintAsciiFormat (VariableName, sizeof VariableName, "Boot%04x",
ActiveOption[Idx].BootOption->BootCurrent); ActiveOption[Idx].BootOption->OptionNumber);
// //
// "The space consumed by the deleted variable may not be available until // "The space consumed by the deleted variable may not be available until
@ -1699,6 +1738,17 @@ SetBootOrderFromQemu (
UINTN TranslatedSize; UINTN TranslatedSize;
CHAR16 Translated[TRANSLATION_OUTPUT_SIZE]; CHAR16 Translated[TRANSLATION_OUTPUT_SIZE];
EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions;
UINTN BootOptionCount;
//
// The QemuBootOrderLib is linked by OvmfPkg and ArmVirtPkg.
// OvmfPkg was changed to use the new BDS @ MdeModulePkg, so boot options
// are no longer stored in linked list.
// But we don't change the QemuBootOrderLib class interface because
// ArmVirtPkg are still using old BDS @ IntelFrameworkModulePkg.
//
ASSERT (BootOptionList == NULL);
Status = QemuFwCfgFindFile ("bootorder", &FwCfgItem, &FwCfgSize); Status = QemuFwCfgFindFile ("bootorder", &FwCfgItem, &FwCfgSize);
if (Status != RETURN_SUCCESS) { if (Status != RETURN_SUCCESS) {
@ -1736,11 +1786,21 @@ SetBootOrderFromQemu (
goto ErrorFreeFwCfg; goto ErrorFreeFwCfg;
} }
Status = CollectActiveOptions (BootOptionList, &ActiveOption, &ActiveCount); BootOptions = EfiBootManagerGetLoadOptions (
if (RETURN_ERROR (Status)) { &BootOptionCount, LoadOptionTypeBoot
);
if (BootOptions == NULL) {
Status = RETURN_NOT_FOUND;
goto ErrorFreeBootOrder; goto ErrorFreeBootOrder;
} }
Status = CollectActiveOptions (
BootOptions, BootOptionCount, &ActiveOption, &ActiveCount
);
if (RETURN_ERROR (Status)) {
goto ErrorFreeBootOptions;
}
if (FeaturePcdGet (PcdQemuBootOrderPciTranslation)) { if (FeaturePcdGet (PcdQemuBootOrderPciTranslation)) {
Status = CreateExtraRootBusMap (&ExtraPciRoots); Status = CreateExtraRootBusMap (&ExtraPciRoots);
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
@ -1770,7 +1830,7 @@ SetBootOrderFromQemu (
if (Match ( if (Match (
Translated, Translated,
TranslatedSize, // contains length, not size, in CHAR16's here TranslatedSize, // contains length, not size, in CHAR16's here
ActiveOption[Idx].BootOption->DevicePath ActiveOption[Idx].BootOption->FilePath
) )
) { ) {
// //
@ -1831,6 +1891,9 @@ ErrorFreeExtraPciRoots:
ErrorFreeActiveOption: ErrorFreeActiveOption:
FreePool (ActiveOption); FreePool (ActiveOption);
ErrorFreeBootOptions:
EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount);
ErrorFreeBootOrder: ErrorFreeBootOrder:
FreePool (BootOrder.Data); FreePool (BootOrder.Data);

View File

@ -36,14 +36,14 @@
[Packages] [Packages]
MdePkg/MdePkg.dec MdePkg/MdePkg.dec
IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec MdeModulePkg/MdeModulePkg.dec
OvmfPkg/OvmfPkg.dec OvmfPkg/OvmfPkg.dec
[LibraryClasses] [LibraryClasses]
QemuFwCfgLib QemuFwCfgLib
DebugLib DebugLib
MemoryAllocationLib MemoryAllocationLib
GenericBdsLib UefiBootManagerLib
UefiBootServicesTableLib UefiBootServicesTableLib
UefiRuntimeServicesTableLib UefiRuntimeServicesTableLib
BaseLib BaseLib