X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=OvmfPkg%2FLibrary%2FQemuBootOrderLib%2FQemuBootOrderLib.c;h=b699970b12ab4603d1a2a1a68ea98216820b0c8f;hp=15065b7c3d50699a9bbb8c54b38ee57ad8a6a948;hb=5851b8253a31db5a5e62847cf0c70f5629542de0;hpb=d7c0dfaef26ca1693529360ed6c6de0021e19595
diff --git a/OvmfPkg/Library/QemuBootOrderLib/QemuBootOrderLib.c b/OvmfPkg/Library/QemuBootOrderLib/QemuBootOrderLib.c
index 15065b7c3d..b699970b12 100644
--- a/OvmfPkg/Library/QemuBootOrderLib/QemuBootOrderLib.c
+++ b/OvmfPkg/Library/QemuBootOrderLib/QemuBootOrderLib.c
@@ -2,7 +2,7 @@
Rewrite the BootOrder NvVar based on QEMU's "bootorder" fw_cfg file.
Copyright (C) 2012 - 2014, Red Hat, Inc.
- Copyright (c) 2013, Intel Corporation. All rights reserved.
+ Copyright (c) 2013 - 2016, Intel Corporation. All rights reserved.
This program and the accompanying materials are licensed and made available
under the terms and conditions of the BSD License which accompanies this
@@ -16,7 +16,7 @@
#include
#include
#include
-#include
+#include
#include
#include
#include
@@ -253,8 +253,10 @@ typedef struct {
LOAD_OPTION_ACTIVE attribute.
**/
typedef struct {
- CONST BDS_COMMON_OPTION *BootOption; // reference only, no ownership
- BOOLEAN Appended; // has been added to a BOOT_ORDER?
+ CONST EFI_BOOT_MANAGER_LOAD_OPTION *BootOption; // reference only, no
+ // ownership
+ BOOLEAN Appended; // has been added to a
+ // BOOT_ORDER?
} ACTIVE_OPTION;
@@ -300,7 +302,7 @@ BootOrderAppend (
}
BootOrder->Data[BootOrder->Produced++] =
- ActiveOption->BootOption->BootCurrent;
+ (UINT16) ActiveOption->BootOption->OptionNumber;
ActiveOption->Appended = TRUE;
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
- BdsLibEnumerateAllBootOption().
+ @param[in] BootOptions A boot option array, created with
+ EfiBootManagerRefreshAllBootOption () and
+ EfiBootManagerGetLoadOptions ().
- @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[in] BootOptionCount The number of elements in BootOptions.
- @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_NOT_FOUND No active entry has been found in
- BootOptionList.
+ BootOptions.
@retval RETURN_OUT_OF_RESOURCES Memory allocation failed.
@@ -331,11 +336,13 @@ BootOrderAppend (
STATIC
RETURN_STATUS
CollectActiveOptions (
- IN CONST LIST_ENTRY *BootOptionList,
- OUT ACTIVE_OPTION **ActiveOption,
- OUT UINTN *Count
+ IN CONST EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions,
+ IN UINTN BootOptionCount,
+ OUT ACTIVE_OPTION **ActiveOption,
+ OUT UINTN *Count
)
{
+ UINTN Index;
UINTN ScanMode;
*ActiveOption = NULL;
@@ -346,22 +353,15 @@ CollectActiveOptions (
// - store links to active entries.
//
for (ScanMode = 0; ScanMode < 2; ++ScanMode) {
- CONST LIST_ENTRY *Link;
-
- Link = BootOptionList->ForwardLink;
*Count = 0;
- while (Link != BootOptionList) {
- CONST BDS_COMMON_OPTION *Current;
-
- Current = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE);
- if (IS_LOAD_OPTION_TYPE (Current->Attribute, LOAD_OPTION_ACTIVE)) {
+ for (Index = 0; Index < BootOptionCount; Index++) {
+ if ((BootOptions[Index].Attributes & LOAD_OPTION_ACTIVE) != 0) {
if (ScanMode == 1) {
- (*ActiveOption)[*Count].BootOption = Current;
+ (*ActiveOption)[*Count].BootOption = &BootOptions[Index];
(*ActiveOption)[*Count].Appended = FALSE;
}
++*Count;
}
- Link = Link->ForwardLink;
}
if (ScanMode == 0) {
@@ -707,7 +707,7 @@ TranslatePciOfwNodes (
// Parse the OFW nodes starting with the first non-bridge node.
//
PciDevFun[1] = 0;
- NumEntries = sizeof (PciDevFun) / sizeof (PciDevFun[0]);
+ NumEntries = ARRAY_SIZE (PciDevFun);
if (ParseUnitAddressHexList (
OfwNode[FirstNonBridge].UnitAddress,
PciDevFun,
@@ -786,11 +786,11 @@ TranslatePciOfwNodes (
//
// UEFI device path:
//
- // PciRoot(0x0)/Pci(0x1F,0x2)/Sata(0x1,0x0,0x0)
- // ^ ^ ^
- // | | LUN (always 0 on Q35)
+ // PciRoot(0x0)/Pci(0x1F,0x2)/Sata(0x1,0xFFFF,0x0)
+ // ^ ^ ^
+ // | | LUN (always 0 on Q35)
// | port multiplier port number,
- // | always 0 on Q35
+ // | always 0xFFFF on Q35
// channel (port) number
//
UINT64 Channel;
@@ -805,7 +805,7 @@ TranslatePciOfwNodes (
Written = UnicodeSPrintAsciiFormat (
Translated,
*TranslatedSize * sizeof (*Translated), // BufferSize in bytes
- "PciRoot(0x%x)%s/Pci(0x%Lx,0x%Lx)/Sata(0x%Lx,0x0,0x0)",
+ "PciRoot(0x%x)%s/Pci(0x%Lx,0x%Lx)/Sata(0x%Lx,0xFFFF,0x0)",
PciRoot,
Bridges,
PciDevFun[0],
@@ -872,13 +872,13 @@ TranslatePciOfwNodes (
//
// UEFI device path prefix:
//
- // PciRoot(0x0)/Pci(0x6,0x0)/HD( -- if PCI function is 0 or absent
- // PciRoot(0x0)/Pci(0x6,0x3)/HD( -- if PCI function is present and nonzero
+ // PciRoot(0x0)/Pci(0x6,0x0) -- if PCI function is 0 or absent
+ // PciRoot(0x0)/Pci(0x6,0x3) -- if PCI function is present and nonzero
//
Written = UnicodeSPrintAsciiFormat (
Translated,
*TranslatedSize * sizeof (*Translated), // BufferSize in bytes
- "PciRoot(0x%x)%s/Pci(0x%Lx,0x%Lx)/HD(",
+ "PciRoot(0x%x)%s/Pci(0x%Lx,0x%Lx)",
PciRoot,
Bridges,
PciDevFun[0],
@@ -910,7 +910,7 @@ TranslatePciOfwNodes (
UINT64 TargetLun[2];
TargetLun[1] = 0;
- NumEntries = sizeof (TargetLun) / sizeof (TargetLun[0]);
+ NumEntries = ARRAY_SIZE (TargetLun);
if (ParseUnitAddressHexList (
OfwNode[FirstNonBridge + 2].UnitAddress,
TargetLun,
@@ -958,7 +958,7 @@ TranslatePciOfwNodes (
UINTN RequiredEntries;
UINT8 *Eui64;
- RequiredEntries = sizeof (Namespace) / sizeof (Namespace[0]);
+ RequiredEntries = ARRAY_SIZE (Namespace);
NumEntries = RequiredEntries;
if (ParseUnitAddressHexList (
OfwNode[FirstNonBridge + 1].UnitAddress,
@@ -986,6 +986,50 @@ TranslatePciOfwNodes (
Eui64[7], Eui64[6], Eui64[5], Eui64[4],
Eui64[3], Eui64[2], Eui64[1], Eui64[0]
);
+ } else if (NumNodes >= FirstNonBridge + 2 &&
+ SubstringEq (OfwNode[FirstNonBridge + 0].DriverName, "usb") &&
+ SubstringEq (OfwNode[FirstNonBridge + 1].DriverName, "storage")) {
+ //
+ // OpenFirmware device path (usb-storage device in XHCI port):
+ //
+ // /pci@i0cf8/usb@3[,1]/storage@2/channel@0/disk@0,0
+ // ^ ^ ^ ^ ^ ^ ^
+ // | | | | fixed fixed
+ // | | | XHCI port number, 1-based
+ // | | PCI function corresponding to XHCI (optional)
+ // | PCI slot holding XHCI
+ // PCI root at system bus port, PIO
+ //
+ // UEFI device path prefix:
+ //
+ // PciRoot(0x0)/Pci(0x3,0x1)/USB(0x1,0x0)
+ // ^ ^
+ // | XHCI port number in 0-based notation
+ // 0x0 if PCI function is 0, or absent from OFW
+ //
+ RETURN_STATUS ParseStatus;
+ UINT64 OneBasedXhciPort;
+
+ NumEntries = 1;
+ ParseStatus = ParseUnitAddressHexList (
+ OfwNode[FirstNonBridge + 1].UnitAddress,
+ &OneBasedXhciPort,
+ &NumEntries
+ );
+ if (RETURN_ERROR (ParseStatus) || OneBasedXhciPort == 0) {
+ return RETURN_UNSUPPORTED;
+ }
+
+ Written = UnicodeSPrintAsciiFormat (
+ Translated,
+ *TranslatedSize * sizeof (*Translated), // BufferSize in bytes
+ "PciRoot(0x%x)%s/Pci(0x%Lx,0x%Lx)/USB(0x%Lx,0x0)",
+ PciRoot,
+ Bridges,
+ PciDevFun[0],
+ PciDevFun[1],
+ OneBasedXhciPort - 1
+ );
} else {
//
// Generic OpenFirmware device path for PCI devices:
@@ -1117,12 +1161,12 @@ TranslateMmioOfwNodes (
//
// UEFI device path prefix:
//
- // /HD(
+ //
//
Written = UnicodeSPrintAsciiFormat (
Translated,
*TranslatedSize * sizeof (*Translated), // BufferSize in bytes
- "%s/HD(",
+ "%s",
VenHwString
);
} else if (NumNodes >= 3 &&
@@ -1145,7 +1189,7 @@ TranslateMmioOfwNodes (
UINT64 TargetLun[2];
TargetLun[1] = 0;
- NumEntries = sizeof (TargetLun) / sizeof (TargetLun[0]);
+ NumEntries = ARRAY_SIZE (TargetLun);
if (ParseUnitAddressHexList (
OfwNode[2].UnitAddress,
TargetLun,
@@ -1437,11 +1481,17 @@ BOOLEAN
Match (
IN CONST CHAR16 *Translated,
IN UINTN TranslatedLength,
- IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
)
{
- CHAR16 *Converted;
- BOOLEAN Result;
+ CHAR16 *Converted;
+ BOOLEAN Result;
+ VOID *FileBuffer;
+ UINTN FileSize;
+ EFI_DEVICE_PATH_PROTOCOL *AbsDevicePath;
+ CHAR16 *AbsConverted;
+ BOOLEAN Shortform;
+ EFI_DEVICE_PATH_PROTOCOL *Node;
Converted = ConvertDevicePathToText (
DevicePath,
@@ -1452,24 +1502,57 @@ Match (
return FALSE;
}
+ Result = FALSE;
+ Shortform = 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.
+ // Expand the short-form device path to full device path
//
- Result = FALSE;
- if (DevicePathType (DevicePath) == MEDIA_DEVICE_PATH &&
- DevicePathSubType (DevicePath) == MEDIA_HARDDRIVE_DP) {
- EFI_DEVICE_PATH_PROTOCOL *AbsDevicePath;
- CHAR16 *AbsConverted;
-
- AbsDevicePath = BdsExpandPartitionPartialDevicePathToFull (
- (HARDDRIVE_DEVICE_PATH *) DevicePath);
- if (AbsDevicePath == NULL) {
+ 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;
+ }
+ }
+ }
+
+ //
+ // Attempt to expand any relative UEFI device path to
+ // an absolute device path first.
+ //
+ if (Shortform) {
+ FileBuffer = EfiBootManagerGetLoadOptionBuffer (
+ DevicePath, &AbsDevicePath, &FileSize
+ );
+ if (FileBuffer == NULL) {
goto Exit;
}
+ FreePool (FileBuffer);
AbsConverted = ConvertDevicePathToText (AbsDevicePath, FALSE, FALSE);
+ FreePool (AbsDevicePath);
if (AbsConverted == NULL) {
goto Exit;
}
@@ -1538,11 +1621,11 @@ BootOrderComplete (
Idx = 0;
while (!RETURN_ERROR (Status) && Idx < ActiveCount) {
if (!ActiveOption[Idx].Appended) {
- CONST BDS_COMMON_OPTION *Current;
- CONST EFI_DEVICE_PATH_PROTOCOL *FirstNode;
+ CONST EFI_BOOT_MANAGER_LOAD_OPTION *Current;
+ CONST EFI_DEVICE_PATH_PROTOCOL *FirstNode;
Current = ActiveOption[Idx].BootOption;
- FirstNode = Current->DevicePath;
+ FirstNode = Current->FilePath;
if (FirstNode != NULL) {
CHAR16 *Converted;
STATIC CHAR16 ConvFallBack[] = L"";
@@ -1635,7 +1718,7 @@ PruneBootVariables (
CHAR16 VariableName[9];
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
@@ -1657,12 +1740,11 @@ PruneBootVariables (
Attempt to retrieve the "bootorder" fw_cfg file from QEMU. Translate the
OpenFirmware device paths therein to UEFI device path fragments. Match the
- translated fragments against BootOptionList, and rewrite the BootOrder NvVar
- so that it corresponds to the order described in fw_cfg.
-
- @param[in] BootOptionList A boot option list, created with
- BdsLibEnumerateAllBootOption ().
+ translated fragments against the current list of boot options, and rewrite
+ the BootOrder NvVar so that it corresponds to the order described in fw_cfg.
+ Platform BDS should call this function after EfiBootManagerConnectAll () and
+ EfiBootManagerRefreshAllBootOption () return.
@retval RETURN_SUCCESS BootOrder NvVar rewritten.
@@ -1681,8 +1763,9 @@ PruneBootVariables (
**/
RETURN_STATUS
+EFIAPI
SetBootOrderFromQemu (
- IN CONST LIST_ENTRY *BootOptionList
+ VOID
)
{
RETURN_STATUS Status;
@@ -1699,6 +1782,8 @@ SetBootOrderFromQemu (
UINTN TranslatedSize;
CHAR16 Translated[TRANSLATION_OUTPUT_SIZE];
+ EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions;
+ UINTN BootOptionCount;
Status = QemuFwCfgFindFile ("bootorder", &FwCfgItem, &FwCfgSize);
if (Status != RETURN_SUCCESS) {
@@ -1736,11 +1821,21 @@ SetBootOrderFromQemu (
goto ErrorFreeFwCfg;
}
- Status = CollectActiveOptions (BootOptionList, &ActiveOption, &ActiveCount);
- if (RETURN_ERROR (Status)) {
+ BootOptions = EfiBootManagerGetLoadOptions (
+ &BootOptionCount, LoadOptionTypeBoot
+ );
+ if (BootOptions == NULL) {
+ Status = RETURN_NOT_FOUND;
goto ErrorFreeBootOrder;
}
+ Status = CollectActiveOptions (
+ BootOptions, BootOptionCount, &ActiveOption, &ActiveCount
+ );
+ if (RETURN_ERROR (Status)) {
+ goto ErrorFreeBootOptions;
+ }
+
if (FeaturePcdGet (PcdQemuBootOrderPciTranslation)) {
Status = CreateExtraRootBusMap (&ExtraPciRoots);
if (EFI_ERROR (Status)) {
@@ -1753,7 +1848,7 @@ SetBootOrderFromQemu (
//
// translate each OpenFirmware path
//
- TranslatedSize = sizeof (Translated) / sizeof (Translated[0]);
+ TranslatedSize = ARRAY_SIZE (Translated);
Status = TranslateOfwPath (&FwCfgPtr, ExtraPciRoots, Translated,
&TranslatedSize);
while (Status == RETURN_SUCCESS ||
@@ -1767,10 +1862,11 @@ SetBootOrderFromQemu (
// match translated OpenFirmware path against all active boot options
//
for (Idx = 0; Idx < ActiveCount; ++Idx) {
- if (Match (
+ if (!ActiveOption[Idx].Appended &&
+ Match (
Translated,
TranslatedSize, // contains length, not size, in CHAR16's here
- ActiveOption[Idx].BootOption->DevicePath
+ ActiveOption[Idx].BootOption->FilePath
)
) {
//
@@ -1780,12 +1876,11 @@ SetBootOrderFromQemu (
if (Status != RETURN_SUCCESS) {
goto ErrorFreeExtraPciRoots;
}
- break;
}
} // scanned all active boot options
} // translation successful
- TranslatedSize = sizeof (Translated) / sizeof (Translated[0]);
+ TranslatedSize = ARRAY_SIZE (Translated);
Status = TranslateOfwPath (&FwCfgPtr, ExtraPciRoots, Translated,
&TranslatedSize);
} // scanning of OpenFirmware paths done
@@ -1815,7 +1910,8 @@ SetBootOrderFromQemu (
BootOrder.Data
);
if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "%a: setting BootOrder: %r\n", __FUNCTION__, Status));
+ DEBUG ((DEBUG_ERROR, "%a: setting BootOrder: %r\n", __FUNCTION__,
+ Status));
goto ErrorFreeExtraPciRoots;
}
@@ -1831,6 +1927,9 @@ ErrorFreeExtraPciRoots:
ErrorFreeActiveOption:
FreePool (ActiveOption);
+ErrorFreeBootOptions:
+ EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount);
+
ErrorFreeBootOrder:
FreePool (BootOrder.Data);
@@ -1848,6 +1947,7 @@ ErrorFreeFwCfg:
@return The TimeoutDefault argument for PlatformBdsEnterFrontPage().
**/
UINT16
+EFIAPI
GetFrontPageTimeoutFromQemu (
VOID
)