summaryrefslogtreecommitdiffstats
path: root/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Pci/PciBusDxe/PciDriverOverride.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Pci/PciBusDxe/PciDriverOverride.c')
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Pci/PciBusDxe/PciDriverOverride.c188
1 files changed, 188 insertions, 0 deletions
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Pci/PciBusDxe/PciDriverOverride.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Pci/PciBusDxe/PciDriverOverride.c
new file mode 100644
index 00000000..0c3f684c
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Pci/PciBusDxe/PciDriverOverride.c
@@ -0,0 +1,188 @@
+/** @file
+ Functions implementation for Bus Specific Driver Override protocol.
+
+Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "PciBus.h"
+
+/**
+ Initializes a PCI Driver Override Instance.
+
+ @param PciIoDevice PCI Device instance.
+
+**/
+VOID
+InitializePciDriverOverrideInstance (
+ IN OUT PCI_IO_DEVICE *PciIoDevice
+ )
+{
+ PciIoDevice->PciDriverOverride.GetDriver = GetDriver;
+}
+
+/**
+ Find the image handle whose path equals to ImagePath.
+
+ @param ImagePath Image path.
+
+ @return Image handle.
+**/
+EFI_HANDLE
+LocateImageHandle (
+ IN EFI_DEVICE_PATH_PROTOCOL *ImagePath
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE *Handles;
+ UINTN Index;
+ UINTN HandleNum;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ UINTN ImagePathSize;
+ EFI_HANDLE ImageHandle;
+
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiLoadedImageDevicePathProtocolGuid,
+ NULL,
+ &HandleNum,
+ &Handles
+ );
+ if (EFI_ERROR (Status)) {
+ return NULL;
+ }
+
+ ImageHandle = NULL;
+ ImagePathSize = GetDevicePathSize (ImagePath);
+
+ for (Index = 0; Index < HandleNum; Index++) {
+ Status = gBS->HandleProtocol (Handles[Index], &gEfiLoadedImageDevicePathProtocolGuid, (VOID **) &DevicePath);
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+ if ((ImagePathSize == GetDevicePathSize (DevicePath)) &&
+ (CompareMem (ImagePath, DevicePath, ImagePathSize) == 0)
+ ) {
+ ImageHandle = Handles[Index];
+ break;
+ }
+ }
+
+ FreePool (Handles);
+ return ImageHandle;
+}
+
+/**
+ Uses a bus specific algorithm to retrieve a driver image handle for a controller.
+
+ @param This A pointer to the EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL instance.
+ @param DriverImageHandle On input, a pointer to the previous driver image handle returned
+ by GetDriver(). On output, a pointer to the next driver
+ image handle. Passing in a NULL, will return the first driver
+ image handle.
+
+ @retval EFI_SUCCESS A bus specific override driver is returned in DriverImageHandle.
+ @retval EFI_NOT_FOUND The end of the list of override drivers was reached.
+ A bus specific override driver is not returned in DriverImageHandle.
+ @retval EFI_INVALID_PARAMETER DriverImageHandle is not a handle that was returned on a
+ previous call to GetDriver().
+
+**/
+EFI_STATUS
+EFIAPI
+GetDriver (
+ IN EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL *This,
+ IN OUT EFI_HANDLE *DriverImageHandle
+ )
+{
+ PCI_IO_DEVICE *PciIoDevice;
+ LIST_ENTRY *Link;
+ PCI_DRIVER_OVERRIDE_LIST *Override;
+ BOOLEAN ReturnNext;
+
+ Override = NULL;
+ PciIoDevice = PCI_IO_DEVICE_FROM_PCI_DRIVER_OVERRIDE_THIS (This);
+ ReturnNext = (BOOLEAN) (*DriverImageHandle == NULL);
+ for ( Link = GetFirstNode (&PciIoDevice->OptionRomDriverList)
+ ; !IsNull (&PciIoDevice->OptionRomDriverList, Link)
+ ; Link = GetNextNode (&PciIoDevice->OptionRomDriverList, Link)
+ ) {
+
+ Override = DRIVER_OVERRIDE_FROM_LINK (Link);
+
+ if (ReturnNext) {
+ if (Override->DriverImageHandle == NULL) {
+ Override->DriverImageHandle = LocateImageHandle (Override->DriverImagePath);
+ }
+
+ if (Override->DriverImageHandle == NULL) {
+ //
+ // The Option ROM identified by Override->DriverImagePath is not loaded.
+ //
+ continue;
+ } else {
+ *DriverImageHandle = Override->DriverImageHandle;
+ return EFI_SUCCESS;
+ }
+ }
+
+ if (*DriverImageHandle == Override->DriverImageHandle) {
+ ReturnNext = TRUE;
+ }
+ }
+
+ ASSERT (IsNull (&PciIoDevice->OptionRomDriverList, Link));
+ //
+ // ReturnNext indicates a handle match happens.
+ // If all nodes are checked without handle match happening,
+ // the DriverImageHandle should be a invalid handle.
+ //
+ if (ReturnNext) {
+ return EFI_NOT_FOUND;
+ } else {
+ return EFI_INVALID_PARAMETER;
+ }
+}
+
+/**
+ Add an overriding driver image.
+
+ @param PciIoDevice Instance of PciIo device.
+ @param DriverImageHandle Image handle of newly added driver image.
+ @param DriverImagePath Device path of newly added driver image.
+
+ @retval EFI_SUCCESS Successfully added driver.
+ @retval EFI_OUT_OF_RESOURCES No memory resource for new driver instance.
+ @retval other Some error occurred when locating gEfiLoadedImageProtocolGuid.
+
+**/
+EFI_STATUS
+AddDriver (
+ IN PCI_IO_DEVICE *PciIoDevice,
+ IN EFI_HANDLE DriverImageHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *DriverImagePath
+ )
+{
+ PCI_DRIVER_OVERRIDE_LIST *Node;
+
+ //
+ // Caller should pass in either Image Handle or Image Path, but not both.
+ //
+ ASSERT ((DriverImageHandle == NULL) || (DriverImagePath == NULL));
+
+ Node = AllocateZeroPool (sizeof (PCI_DRIVER_OVERRIDE_LIST));
+ if (Node == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Node->Signature = DRIVER_OVERRIDE_SIGNATURE;
+ Node->DriverImageHandle = DriverImageHandle;
+ Node->DriverImagePath = DuplicateDevicePath (DriverImagePath);
+
+ InsertTailList (&PciIoDevice->OptionRomDriverList, &Node->Link);
+
+ PciIoDevice->BusOverride = TRUE;
+ return EFI_SUCCESS;
+}
+