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 )