OvmfPkg: Duplicate QemuBootOrderLib to QemuNewBootOrderLib

QemuNewBootOrderLib will be changed to work with MdeModulePkg/BDS.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
This commit is contained in:
Ruiyu Ni 2016-04-15 18:19:29 +08:00
parent 035ce3b37c
commit 6b40e66a48
4 changed files with 2312 additions and 0 deletions

View File

@ -0,0 +1,313 @@
/** @file
Map positions of extra PCI root buses to bus numbers.
Copyright (C) 2015, Red Hat, Inc.
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
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include <Library/DebugLib.h>
#include <Library/DevicePathLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/OrderedCollectionLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Protocol/DevicePath.h>
#include <Protocol/PciRootBridgeIo.h>
#include "ExtraRootBusMap.h"
//
// The BusNumbers field is an array with Count elements. The elements increase
// strictry monotonically. Zero is not an element (because the zero bus number
// belongs to the "main" root bus, never to an extra root bus). Offset N in the
// array maps the extra root bus with position (N+1) to its bus number (because
// the root bus with position 0 is always the main root bus, therefore we don't
// store it).
//
// If there are no extra root buses in the system, then Count is 0, and
// BusNumbers is NULL.
//
struct EXTRA_ROOT_BUS_MAP_STRUCT {
UINT32 *BusNumbers;
UINTN Count;
};
/**
An ORDERED_COLLECTION_USER_COMPARE function that compares root bridge
protocol device paths based on UID.
@param[in] UserStruct1 Pointer to the first ACPI_HID_DEVICE_PATH.
@param[in] UserStruct2 Pointer to the second ACPI_HID_DEVICE_PATH.
@retval <0 If UserStruct1 compares less than UserStruct2.
@retval 0 If UserStruct1 compares equal to UserStruct2.
@retval >0 If UserStruct1 compares greater than UserStruct2.
**/
STATIC
INTN
EFIAPI
RootBridgePathCompare (
IN CONST VOID *UserStruct1,
IN CONST VOID *UserStruct2
)
{
CONST ACPI_HID_DEVICE_PATH *Acpi1;
CONST ACPI_HID_DEVICE_PATH *Acpi2;
Acpi1 = UserStruct1;
Acpi2 = UserStruct2;
return Acpi1->UID < Acpi2->UID ? -1 :
Acpi1->UID > Acpi2->UID ? 1 :
0;
}
/**
An ORDERED_COLLECTION_KEY_COMPARE function that compares a root bridge
protocol device path against a UID.
@param[in] StandaloneKey Pointer to the bare UINT32 UID.
@param[in] UserStruct Pointer to the ACPI_HID_DEVICE_PATH with the
embedded UINT32 UID.
@retval <0 If StandaloneKey compares less than UserStruct's key.
@retval 0 If StandaloneKey compares equal to UserStruct's key.
@retval >0 If StandaloneKey compares greater than UserStruct's key.
**/
STATIC
INTN
EFIAPI
RootBridgePathKeyCompare (
IN CONST VOID *StandaloneKey,
IN CONST VOID *UserStruct
)
{
CONST UINT32 *Uid;
CONST ACPI_HID_DEVICE_PATH *Acpi;
Uid = StandaloneKey;
Acpi = UserStruct;
return *Uid < Acpi->UID ? -1 :
*Uid > Acpi->UID ? 1 :
0;
}
/**
Create a structure that maps the relative positions of PCI root buses to bus
numbers.
In the "bootorder" fw_cfg file, QEMU refers to extra PCI root buses by their
positions, in relative root bus number order, not by their actual PCI bus
numbers. The ACPI HID device path nodes however that are associated with
PciRootBridgeIo protocol instances in the system have their UID fields set to
the bus numbers. Create a map that gives, for each extra PCI root bus's
position (ie. "serial number") its actual PCI bus number.
@param[out] ExtraRootBusMap The data structure implementing the map.
@retval EFI_SUCCESS ExtraRootBusMap has been populated.
@retval EFI_OUT_OF_RESOURCES Memory allocation failed.
@retval EFI_ALREADY_STARTED A duplicate root bus number has been found in
the system. (This should never happen.)
@return Error codes returned by
gBS->LocateHandleBuffer() and
gBS->HandleProtocol().
**/
EFI_STATUS
CreateExtraRootBusMap (
OUT EXTRA_ROOT_BUS_MAP **ExtraRootBusMap
)
{
EFI_STATUS Status;
UINTN NumHandles;
EFI_HANDLE *Handles;
ORDERED_COLLECTION *Collection;
EXTRA_ROOT_BUS_MAP *Map;
UINTN Idx;
ORDERED_COLLECTION_ENTRY *Entry, *Entry2;
//
// Handles and Collection are temporary / helper variables, while in Map we
// build the return value.
//
Status = gBS->LocateHandleBuffer (ByProtocol,
&gEfiPciRootBridgeIoProtocolGuid, NULL /* SearchKey */,
&NumHandles, &Handles);
if (EFI_ERROR (Status)) {
return Status;
}
Collection = OrderedCollectionInit (RootBridgePathCompare,
RootBridgePathKeyCompare);
if (Collection == NULL) {
Status = EFI_OUT_OF_RESOURCES;
goto FreeHandles;
}
Map = AllocateZeroPool (sizeof *Map);
if (Map == NULL) {
Status = EFI_OUT_OF_RESOURCES;
goto FreeCollection;
}
//
// Collect the ACPI device path protocols of the root bridges.
//
for (Idx = 0; Idx < NumHandles; ++Idx) {
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
Status = gBS->HandleProtocol (Handles[Idx], &gEfiDevicePathProtocolGuid,
(VOID**)&DevicePath);
if (EFI_ERROR (Status)) {
goto FreeMap;
}
//
// Examine if the device path is an ACPI HID one, and if so, if UID is
// nonzero (ie. the root bridge that the bus number belongs to is "extra",
// not the main one). In that case, link the device path into Collection.
//
if (DevicePathType (DevicePath) == ACPI_DEVICE_PATH &&
DevicePathSubType (DevicePath) == ACPI_DP &&
((ACPI_HID_DEVICE_PATH *)DevicePath)->HID == EISA_PNP_ID(0x0A03) &&
((ACPI_HID_DEVICE_PATH *)DevicePath)->UID > 0) {
Status = OrderedCollectionInsert (Collection, NULL, DevicePath);
if (EFI_ERROR (Status)) {
goto FreeMap;
}
++Map->Count;
}
}
if (Map->Count > 0) {
//
// At least one extra PCI root bus exists.
//
Map->BusNumbers = AllocatePool (Map->Count * sizeof *Map->BusNumbers);
if (Map->BusNumbers == NULL) {
Status = EFI_OUT_OF_RESOURCES;
goto FreeMap;
}
}
//
// Now collect the bus numbers of the extra PCI root buses into Map.
//
Idx = 0;
Entry = OrderedCollectionMin (Collection);
while (Idx < Map->Count) {
ACPI_HID_DEVICE_PATH *Acpi;
ASSERT (Entry != NULL);
Acpi = OrderedCollectionUserStruct (Entry);
Map->BusNumbers[Idx] = Acpi->UID;
DEBUG ((EFI_D_VERBOSE,
"%a: extra bus position 0x%Lx maps to bus number (UID) 0x%x\n",
__FUNCTION__, (UINT64)(Idx + 1), Acpi->UID));
++Idx;
Entry = OrderedCollectionNext (Entry);
}
ASSERT (Entry == NULL);
*ExtraRootBusMap = Map;
Status = EFI_SUCCESS;
//
// Fall through in order to release temporaries.
//
FreeMap:
if (EFI_ERROR (Status)) {
if (Map->BusNumbers != NULL) {
FreePool (Map->BusNumbers);
}
FreePool (Map);
}
FreeCollection:
for (Entry = OrderedCollectionMin (Collection); Entry != NULL;
Entry = Entry2) {
Entry2 = OrderedCollectionNext (Entry);
OrderedCollectionDelete (Collection, Entry, NULL);
}
OrderedCollectionUninit (Collection);
FreeHandles:
FreePool (Handles);
return Status;
}
/**
Release a map created with CreateExtraRootBusMap().
@param[in] ExtraRootBusMap The map to release.
*/
VOID
DestroyExtraRootBusMap (
IN EXTRA_ROOT_BUS_MAP *ExtraRootBusMap
)
{
if (ExtraRootBusMap->BusNumbers != NULL) {
FreePool (ExtraRootBusMap->BusNumbers);
}
FreePool (ExtraRootBusMap);
}
/**
Map the position (serial number) of an extra PCI root bus to its bus number.
@param[in] ExtraRootBusMap The map created with CreateExtraRootBusMap();
@param[in] RootBusPos The extra PCI root bus position to map.
@param[out] RootBusNr The bus number belonging to the extra PCI root
bus identified by RootBusPos.
@retval EFI_INVALID_PARAMETER RootBusPos is zero. The zero position
identifies the main root bus, whose bus number
is always zero, and is therefore never
maintained in ExtraRootBusMap.
@retval EFI_NOT_FOUND RootBusPos is not found in ExtraRootBusMap.
@retval EFI_SUCCESS Mapping successful.
**/
EFI_STATUS
MapRootBusPosToBusNr (
IN CONST EXTRA_ROOT_BUS_MAP *ExtraRootBusMap,
IN UINT64 RootBusPos,
OUT UINT32 *RootBusNr
)
{
if (RootBusPos == 0) {
return EFI_INVALID_PARAMETER;
}
if (RootBusPos > ExtraRootBusMap->Count) {
return EFI_NOT_FOUND;
}
*RootBusNr = ExtraRootBusMap->BusNumbers[RootBusPos - 1];
return EFI_SUCCESS;
}

View File

@ -0,0 +1,40 @@
/** @file
Map positions of extra PCI root buses to bus numbers.
Copyright (C) 2015, Red Hat, Inc.
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
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef __EXTRA_ROOT_BUS_MAP_H__
#define __EXTRA_ROOT_BUS_MAP_H__
/**
Incomplete ("opaque") data type implementing the map.
**/
typedef struct EXTRA_ROOT_BUS_MAP_STRUCT EXTRA_ROOT_BUS_MAP;
EFI_STATUS
CreateExtraRootBusMap (
OUT EXTRA_ROOT_BUS_MAP **ExtraRootBusMap
);
VOID
DestroyExtraRootBusMap (
IN EXTRA_ROOT_BUS_MAP *ExtraRootBusMap
);
EFI_STATUS
MapRootBusPosToBusNr (
IN CONST EXTRA_ROOT_BUS_MAP *ExtraRootBusMap,
IN UINT64 RootBusPos,
OUT UINT32 *RootBusNr
);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,68 @@
## @file
# Rewrite the BootOrder NvVar based on QEMU's "bootorder" fw_cfg file.
#
# Copyright (C) 2012 - 2014, Red Hat, Inc.
# Copyright (c) 2007 - 2016, Intel Corporation. All rights reserved.<BR>
#
# 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
# http://opensource.org/licenses/bsd-license.php
#
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR
# IMPLIED.
#
##
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = QemuNewBootOrderLib
FILE_GUID = 1D677A58-C753-4AF1-B552-EFE142DF8F57
MODULE_TYPE = DXE_DRIVER
VERSION_STRING = 1.0
LIBRARY_CLASS = QemuBootOrderLib|DXE_DRIVER
#
# The following information is for reference only and not required by the build
# tools.
#
# VALID_ARCHITECTURES = IA32 X64 IPF EBC ARM AARCH64
#
[Sources]
QemuBootOrderLib.c
ExtraRootBusMap.c
[Packages]
MdePkg/MdePkg.dec
IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec
OvmfPkg/OvmfPkg.dec
[LibraryClasses]
QemuFwCfgLib
DebugLib
MemoryAllocationLib
GenericBdsLib
UefiBootServicesTableLib
UefiRuntimeServicesTableLib
BaseLib
PrintLib
DevicePathLib
BaseMemoryLib
OrderedCollectionLib
[Guids]
gEfiGlobalVariableGuid
gVirtioMmioTransportGuid
[FeaturePcd]
gUefiOvmfPkgTokenSpaceGuid.PcdQemuBootOrderPciTranslation
gUefiOvmfPkgTokenSpaceGuid.PcdQemuBootOrderMmioTranslation
[Pcd]
gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut
[Protocols]
gEfiDevicePathProtocolGuid ## CONSUMES
gEfiPciRootBridgeIoProtocolGuid ## CONSUMES