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