]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Bus/Pci/PciBusDxe/PciDriverOverride.c
MdeModulePkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / PciBusDxe / PciDriverOverride.c
1 /** @file
2 Functions implementation for Bus Specific Driver Override protocol.
3
4 Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6
7 **/
8
9 #include "PciBus.h"
10
11 /**
12 Initializes a PCI Driver Override Instance.
13
14 @param PciIoDevice PCI Device instance.
15
16 **/
17 VOID
18 InitializePciDriverOverrideInstance (
19 IN OUT PCI_IO_DEVICE *PciIoDevice
20 )
21 {
22 PciIoDevice->PciDriverOverride.GetDriver = GetDriver;
23 }
24
25 /**
26 Find the image handle whose path equals to ImagePath.
27
28 @param ImagePath Image path.
29
30 @return Image handle.
31 **/
32 EFI_HANDLE
33 LocateImageHandle (
34 IN EFI_DEVICE_PATH_PROTOCOL *ImagePath
35 )
36 {
37 EFI_STATUS Status;
38 EFI_HANDLE *Handles;
39 UINTN Index;
40 UINTN HandleNum;
41 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
42 UINTN ImagePathSize;
43 EFI_HANDLE ImageHandle;
44
45 Status = gBS->LocateHandleBuffer (
46 ByProtocol,
47 &gEfiLoadedImageDevicePathProtocolGuid,
48 NULL,
49 &HandleNum,
50 &Handles
51 );
52 if (EFI_ERROR (Status)) {
53 return NULL;
54 }
55
56 ImageHandle = NULL;
57 ImagePathSize = GetDevicePathSize (ImagePath);
58
59 for (Index = 0; Index < HandleNum; Index++) {
60 Status = gBS->HandleProtocol (Handles[Index], &gEfiLoadedImageDevicePathProtocolGuid, (VOID **) &DevicePath);
61 if (EFI_ERROR (Status)) {
62 continue;
63 }
64 if ((ImagePathSize == GetDevicePathSize (DevicePath)) &&
65 (CompareMem (ImagePath, DevicePath, ImagePathSize) == 0)
66 ) {
67 ImageHandle = Handles[Index];
68 break;
69 }
70 }
71
72 FreePool (Handles);
73 return ImageHandle;
74 }
75
76 /**
77 Uses a bus specific algorithm to retrieve a driver image handle for a controller.
78
79 @param This A pointer to the EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL instance.
80 @param DriverImageHandle On input, a pointer to the previous driver image handle returned
81 by GetDriver(). On output, a pointer to the next driver
82 image handle. Passing in a NULL, will return the first driver
83 image handle.
84
85 @retval EFI_SUCCESS A bus specific override driver is returned in DriverImageHandle.
86 @retval EFI_NOT_FOUND The end of the list of override drivers was reached.
87 A bus specific override driver is not returned in DriverImageHandle.
88 @retval EFI_INVALID_PARAMETER DriverImageHandle is not a handle that was returned on a
89 previous call to GetDriver().
90
91 **/
92 EFI_STATUS
93 EFIAPI
94 GetDriver (
95 IN EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL *This,
96 IN OUT EFI_HANDLE *DriverImageHandle
97 )
98 {
99 PCI_IO_DEVICE *PciIoDevice;
100 LIST_ENTRY *Link;
101 PCI_DRIVER_OVERRIDE_LIST *Override;
102 BOOLEAN ReturnNext;
103
104 Override = NULL;
105 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_DRIVER_OVERRIDE_THIS (This);
106 ReturnNext = (BOOLEAN) (*DriverImageHandle == NULL);
107 for ( Link = GetFirstNode (&PciIoDevice->OptionRomDriverList)
108 ; !IsNull (&PciIoDevice->OptionRomDriverList, Link)
109 ; Link = GetNextNode (&PciIoDevice->OptionRomDriverList, Link)
110 ) {
111
112 Override = DRIVER_OVERRIDE_FROM_LINK (Link);
113
114 if (ReturnNext) {
115 if (Override->DriverImageHandle == NULL) {
116 Override->DriverImageHandle = LocateImageHandle (Override->DriverImagePath);
117 }
118
119 if (Override->DriverImageHandle == NULL) {
120 //
121 // The Option ROM identified by Override->DriverImagePath is not loaded.
122 //
123 continue;
124 } else {
125 *DriverImageHandle = Override->DriverImageHandle;
126 return EFI_SUCCESS;
127 }
128 }
129
130 if (*DriverImageHandle == Override->DriverImageHandle) {
131 ReturnNext = TRUE;
132 }
133 }
134
135 ASSERT (IsNull (&PciIoDevice->OptionRomDriverList, Link));
136 //
137 // ReturnNext indicates a handle match happens.
138 // If all nodes are checked without handle match happening,
139 // the DriverImageHandle should be a invalid handle.
140 //
141 if (ReturnNext) {
142 return EFI_NOT_FOUND;
143 } else {
144 return EFI_INVALID_PARAMETER;
145 }
146 }
147
148 /**
149 Add an overriding driver image.
150
151 @param PciIoDevice Instance of PciIo device.
152 @param DriverImageHandle Image handle of newly added driver image.
153 @param DriverImagePath Device path of newly added driver image.
154
155 @retval EFI_SUCCESS Successfully added driver.
156 @retval EFI_OUT_OF_RESOURCES No memory resource for new driver instance.
157 @retval other Some error occurred when locating gEfiLoadedImageProtocolGuid.
158
159 **/
160 EFI_STATUS
161 AddDriver (
162 IN PCI_IO_DEVICE *PciIoDevice,
163 IN EFI_HANDLE DriverImageHandle,
164 IN EFI_DEVICE_PATH_PROTOCOL *DriverImagePath
165 )
166 {
167 PCI_DRIVER_OVERRIDE_LIST *Node;
168
169 //
170 // Caller should pass in either Image Handle or Image Path, but not both.
171 //
172 ASSERT ((DriverImageHandle == NULL) || (DriverImagePath == NULL));
173
174 Node = AllocateZeroPool (sizeof (PCI_DRIVER_OVERRIDE_LIST));
175 if (Node == NULL) {
176 return EFI_OUT_OF_RESOURCES;
177 }
178
179 Node->Signature = DRIVER_OVERRIDE_SIGNATURE;
180 Node->DriverImageHandle = DriverImageHandle;
181 Node->DriverImagePath = DuplicateDevicePath (DriverImagePath);
182
183 InsertTailList (&PciIoDevice->OptionRomDriverList, &Node->Link);
184
185 PciIoDevice->BusOverride = TRUE;
186 return EFI_SUCCESS;
187 }
188