]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Bus/Pci/PciBusDxe/PciDriverOverride.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[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
65 if ((ImagePathSize == GetDevicePathSize (DevicePath)) &&
66 (CompareMem (ImagePath, DevicePath, ImagePathSize) == 0)
67 )
68 {
69 ImageHandle = Handles[Index];
70 break;
71 }
72 }
73
74 FreePool (Handles);
75 return ImageHandle;
76 }
77
78 /**
79 Uses a bus specific algorithm to retrieve a driver image handle for a controller.
80
81 @param This A pointer to the EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL instance.
82 @param DriverImageHandle On input, a pointer to the previous driver image handle returned
83 by GetDriver(). On output, a pointer to the next driver
84 image handle. Passing in a NULL, will return the first driver
85 image handle.
86
87 @retval EFI_SUCCESS A bus specific override driver is returned in DriverImageHandle.
88 @retval EFI_NOT_FOUND The end of the list of override drivers was reached.
89 A bus specific override driver is not returned in DriverImageHandle.
90 @retval EFI_INVALID_PARAMETER DriverImageHandle is not a handle that was returned on a
91 previous call to GetDriver().
92
93 **/
94 EFI_STATUS
95 EFIAPI
96 GetDriver (
97 IN EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL *This,
98 IN OUT EFI_HANDLE *DriverImageHandle
99 )
100 {
101 PCI_IO_DEVICE *PciIoDevice;
102 LIST_ENTRY *Link;
103 PCI_DRIVER_OVERRIDE_LIST *Override;
104 BOOLEAN ReturnNext;
105
106 Override = NULL;
107 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_DRIVER_OVERRIDE_THIS (This);
108 ReturnNext = (BOOLEAN)(*DriverImageHandle == NULL);
109 for ( Link = GetFirstNode (&PciIoDevice->OptionRomDriverList)
110 ; !IsNull (&PciIoDevice->OptionRomDriverList, Link)
111 ; Link = GetNextNode (&PciIoDevice->OptionRomDriverList, Link)
112 )
113 {
114 Override = DRIVER_OVERRIDE_FROM_LINK (Link);
115
116 if (ReturnNext) {
117 if (Override->DriverImageHandle == NULL) {
118 Override->DriverImageHandle = LocateImageHandle (Override->DriverImagePath);
119 }
120
121 if (Override->DriverImageHandle == NULL) {
122 //
123 // The Option ROM identified by Override->DriverImagePath is not loaded.
124 //
125 continue;
126 } else {
127 *DriverImageHandle = Override->DriverImageHandle;
128 return EFI_SUCCESS;
129 }
130 }
131
132 if (*DriverImageHandle == Override->DriverImageHandle) {
133 ReturnNext = TRUE;
134 }
135 }
136
137 ASSERT (IsNull (&PciIoDevice->OptionRomDriverList, Link));
138 //
139 // ReturnNext indicates a handle match happens.
140 // If all nodes are checked without handle match happening,
141 // the DriverImageHandle should be a invalid handle.
142 //
143 if (ReturnNext) {
144 return EFI_NOT_FOUND;
145 } else {
146 return EFI_INVALID_PARAMETER;
147 }
148 }
149
150 /**
151 Add an overriding driver image.
152
153 @param PciIoDevice Instance of PciIo device.
154 @param DriverImageHandle Image handle of newly added driver image.
155 @param DriverImagePath Device path of newly added driver image.
156
157 @retval EFI_SUCCESS Successfully added driver.
158 @retval EFI_OUT_OF_RESOURCES No memory resource for new driver instance.
159 @retval other Some error occurred when locating gEfiLoadedImageProtocolGuid.
160
161 **/
162 EFI_STATUS
163 AddDriver (
164 IN PCI_IO_DEVICE *PciIoDevice,
165 IN EFI_HANDLE DriverImageHandle,
166 IN EFI_DEVICE_PATH_PROTOCOL *DriverImagePath
167 )
168 {
169 PCI_DRIVER_OVERRIDE_LIST *Node;
170
171 //
172 // Caller should pass in either Image Handle or Image Path, but not both.
173 //
174 ASSERT ((DriverImageHandle == NULL) || (DriverImagePath == NULL));
175
176 Node = AllocateZeroPool (sizeof (PCI_DRIVER_OVERRIDE_LIST));
177 if (Node == NULL) {
178 return EFI_OUT_OF_RESOURCES;
179 }
180
181 Node->Signature = DRIVER_OVERRIDE_SIGNATURE;
182 Node->DriverImageHandle = DriverImageHandle;
183 Node->DriverImagePath = DuplicateDevicePath (DriverImagePath);
184
185 InsertTailList (&PciIoDevice->OptionRomDriverList, &Node->Link);
186
187 PciIoDevice->BusOverride = TRUE;
188 return EFI_SUCCESS;
189 }