]> git.proxmox.com Git - mirror_edk2.git/blame - EdkModulePkg/Bus/Pci/PciBus/Dxe/PciDriverOverride.c
1) Use FeatureFlag PcdPciBusHotplugDeviceSupport to merge LightPciLib.c with PcdLib.c.
[mirror_edk2.git] / EdkModulePkg / Bus / Pci / PciBus / Dxe / PciDriverOverride.c
CommitLineData
878ddf1f 1/*++\r
2\r
3Copyright (c) 2006, Intel Corporation \r
4All rights reserved. This program and the accompanying materials \r
5are licensed and made available under the terms and conditions of the BSD License \r
6which accompanies this distribution. The full text of the license may be found at \r
7http://opensource.org/licenses/bsd-license.php \r
8 \r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
11\r
12Module Name:\r
13\r
14 PciDriverOverride.c\r
15 \r
16Abstract:\r
17\r
18 PCI Bus Driver\r
19\r
20Revision History\r
21\r
22--*/\r
23\r
24#include "pcibus.h"\r
25\r
26EFI_STATUS\r
27InitializePciDriverOverrideInstance (\r
28 PCI_IO_DEVICE *PciIoDevice\r
29 )\r
30/*++\r
31\r
32Routine Description:\r
33\r
34 Initializes a PCI Driver Override Instance\r
35\r
36Arguments:\r
37 \r
38Returns:\r
39\r
40 None\r
41\r
42--*/\r
43// TODO: PciIoDevice - add argument and description to function comment\r
44// TODO: EFI_SUCCESS - add return value to function comment\r
45{\r
46 PciIoDevice->PciDriverOverride.GetDriver = GetDriver;\r
47 return EFI_SUCCESS;\r
48}\r
49\r
50EFI_STATUS\r
51EFIAPI\r
52GetDriver (\r
53 IN EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL *This,\r
54 IN OUT EFI_HANDLE *DriverImageHandle\r
55 )\r
56/*++\r
57\r
58Routine Description:\r
59\r
60 Get a overriding driver image\r
61\r
62Arguments:\r
63 \r
64Returns:\r
65\r
66 None\r
67\r
68--*/\r
69// TODO: This - add argument and description to function comment\r
70// TODO: DriverImageHandle - add argument and description to function comment\r
71// TODO: EFI_SUCCESS - add return value to function comment\r
72// TODO: EFI_NOT_FOUND - add return value to function comment\r
73// TODO: EFI_SUCCESS - add return value to function comment\r
74// TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
75{\r
76 PCI_IO_DEVICE *PciIoDevice;\r
77 LIST_ENTRY *CurrentLink;\r
78 PCI_DRIVER_OVERRIDE_LIST *Node;\r
79\r
80 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_DRIVER_OVERRIDE_THIS (This);\r
81\r
82 CurrentLink = PciIoDevice->OptionRomDriverList.ForwardLink;\r
83\r
84 while (CurrentLink && CurrentLink != &PciIoDevice->OptionRomDriverList) {\r
85\r
86 Node = DRIVER_OVERRIDE_FROM_LINK (CurrentLink);\r
87\r
88 if (*DriverImageHandle == NULL) {\r
89\r
90 *DriverImageHandle = Node->DriverImageHandle;\r
91 return EFI_SUCCESS;\r
92 }\r
93\r
94 if (*DriverImageHandle == Node->DriverImageHandle) {\r
95\r
96 if (CurrentLink->ForwardLink == &PciIoDevice->OptionRomDriverList ||\r
97 CurrentLink->ForwardLink == NULL) {\r
98 return EFI_NOT_FOUND;\r
99 }\r
100\r
101 //\r
102 // Get next node\r
103 //\r
104 Node = DRIVER_OVERRIDE_FROM_LINK (CurrentLink->ForwardLink);\r
105 *DriverImageHandle = Node->DriverImageHandle;\r
106 return EFI_SUCCESS;\r
107 }\r
108\r
109 CurrentLink = CurrentLink->ForwardLink;\r
110 }\r
111\r
112 return EFI_INVALID_PARAMETER;\r
113}\r
114\r
115EFI_STATUS\r
116AddDriver (\r
117 IN PCI_IO_DEVICE *PciIoDevice,\r
118 IN EFI_HANDLE DriverImageHandle\r
119 )\r
120/*++\r
121\r
122Routine Description:\r
123\r
124 Add a overriding driver image\r
125\r
126Arguments:\r
127 \r
128Returns:\r
129\r
130 None\r
131\r
132--*/\r
133// TODO: PciIoDevice - add argument and description to function comment\r
134// TODO: DriverImageHandle - add argument and description to function comment\r
135// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment\r
136// TODO: EFI_SUCCESS - add return value to function comment\r
137// TODO: EFI_SUCCESS - add return value to function comment\r
138// TODO: EFI_SUCCESS - add return value to function comment\r
139// TODO: EFI_SUCCESS - add return value to function comment\r
140{\r
141 EFI_STATUS Status;\r
406adcd1 142 EFI_IMAGE_DOS_HEADER *DosHdr;\r
143 EFI_IMAGE_NT_HEADERS *PeHdr;\r
878ddf1f 144 EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;\r
145 PCI_DRIVER_OVERRIDE_LIST *Node;\r
406adcd1 146#if (EFI_SPECIFICATION_VERSION < 0x00020000)\r
878ddf1f 147 EFI_DRIVER_OS_HANDOFF_HEADER *DriverOsHandoffHeader;\r
148 EFI_DRIVER_OS_HANDOFF_HEADER *NewDriverOsHandoffHeader;\r
149 EFI_DRIVER_OS_HANDOFF *DriverOsHandoff;\r
150 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
151 EFI_HANDLE DeviceHandle;\r
152 UINTN NumberOfEntries;\r
153 UINTN Size;\r
154 UINTN Index;\r
406adcd1 155#endif\r
878ddf1f 156\r
157 Status = gBS->HandleProtocol (DriverImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **) &LoadedImage);\r
158 if (EFI_ERROR (Status)) {\r
159 return Status;\r
160 }\r
161\r
162 Node = AllocatePool (sizeof (PCI_DRIVER_OVERRIDE_LIST));\r
163 if (Node == NULL) {\r
164 return EFI_OUT_OF_RESOURCES;\r
165 }\r
166\r
167 Node->Signature = DRIVER_OVERRIDE_SIGNATURE;\r
168 Node->DriverImageHandle = DriverImageHandle;\r
169\r
170 InsertTailList (&PciIoDevice->OptionRomDriverList, &(Node->Link));\r
171\r
172 PciIoDevice->BusOverride = TRUE;\r
173\r
406adcd1 174 DosHdr = (EFI_IMAGE_DOS_HEADER *) LoadedImage->ImageBase;\r
175 if (DosHdr->e_magic != EFI_IMAGE_DOS_SIGNATURE) {\r
878ddf1f 176 return EFI_SUCCESS;\r
177 }\r
178\r
406adcd1 179 PeHdr = (EFI_IMAGE_NT_HEADERS *) ((UINTN) LoadedImage->ImageBase + DosHdr->e_lfanew);\r
180\r
181 if (PeHdr->FileHeader.Machine != EFI_IMAGE_MACHINE_EBC) {\r
182 return EFI_SUCCESS;\r
183 }\r
184\r
185#if (EFI_SPECIFICATION_VERSION < 0x00020000)\r
878ddf1f 186 DriverOsHandoffHeader = NULL;\r
187 Status = EfiGetSystemConfigurationTable (&gEfiUgaIoProtocolGuid, (VOID **) &DriverOsHandoffHeader);\r
188 if (!EFI_ERROR (Status) && DriverOsHandoffHeader != NULL) {\r
189 for (Index = 0; Index < DriverOsHandoffHeader->NumberOfEntries; Index++) {\r
190 DriverOsHandoff = (EFI_DRIVER_OS_HANDOFF *)((UINTN)(DriverOsHandoffHeader) + \r
191 DriverOsHandoffHeader->HeaderSize + \r
192 Index * DriverOsHandoffHeader->SizeOfEntries);\r
193 DevicePath = DriverOsHandoff->DevicePath;\r
194 Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &DevicePath, &DeviceHandle);\r
195 if (!EFI_ERROR (Status) && DeviceHandle != NULL && IsDevicePathEnd (DevicePath)) {\r
196 if (DeviceHandle == PciIoDevice->Handle) {\r
197 return EFI_SUCCESS;\r
198 }\r
199 }\r
200 }\r
201\r
202 NumberOfEntries = DriverOsHandoffHeader->NumberOfEntries + 1;\r
203 } else {\r
204 NumberOfEntries = 1;\r
205 }\r
206\r
207 Status = gBS->AllocatePool (\r
208 EfiRuntimeServicesData,\r
209 sizeof (EFI_DRIVER_OS_HANDOFF_HEADER) + NumberOfEntries * sizeof (EFI_DRIVER_OS_HANDOFF),\r
210 (VOID **) &NewDriverOsHandoffHeader\r
211 );\r
212 if (EFI_ERROR (Status)) {\r
213 return Status;\r
214 }\r
215\r
216 if (DriverOsHandoffHeader == NULL) {\r
217 NewDriverOsHandoffHeader->Version = 0;\r
218 NewDriverOsHandoffHeader->HeaderSize = sizeof (EFI_DRIVER_OS_HANDOFF_HEADER);\r
219 NewDriverOsHandoffHeader->SizeOfEntries = sizeof (EFI_DRIVER_OS_HANDOFF);\r
220 NewDriverOsHandoffHeader->NumberOfEntries = (UINT32) NumberOfEntries;\r
221 } else {\r
222 gBS->CopyMem (\r
223 NewDriverOsHandoffHeader,\r
224 DriverOsHandoffHeader,\r
225 DriverOsHandoffHeader->HeaderSize + (NumberOfEntries - 1) * DriverOsHandoffHeader->SizeOfEntries\r
226 );\r
227 NewDriverOsHandoffHeader->NumberOfEntries = (UINT32) NumberOfEntries;\r
228 }\r
229\r
230 DriverOsHandoff = (EFI_DRIVER_OS_HANDOFF *)((UINTN)NewDriverOsHandoffHeader + \r
231 NewDriverOsHandoffHeader->HeaderSize + \r
232 (NumberOfEntries - 1) * NewDriverOsHandoffHeader->SizeOfEntries);\r
233\r
234 //\r
235 // Fill in the EFI_DRIVER_OS_HANDOFF structure\r
236 //\r
237 DriverOsHandoff->Type = EfiUgaDriverFromPciRom;\r
238\r
239 //\r
240 // Compute the size of the device path\r
241 //\r
242 Size = GetDevicePathSize (PciIoDevice->DevicePath);\r
243 if (Size == 0) {\r
244 DriverOsHandoff->DevicePath = NULL;\r
245 } else {\r
246\r
247 //\r
248 // Allocate space for duplicate device path\r
249 //\r
250 Status = gBS->AllocatePool (\r
251 EfiRuntimeServicesData,\r
252 Size,\r
253 (VOID **) &DriverOsHandoff->DevicePath\r
254 );\r
255 if (EFI_ERROR (Status)) {\r
256 gBS->FreePool (NewDriverOsHandoffHeader);\r
257 return Status;\r
258 }\r
259\r
260 //\r
261 // Make copy of device path\r
262 //\r
263 CopyMem (DriverOsHandoff->DevicePath, PciIoDevice->DevicePath, Size);\r
264 }\r
265\r
266 DriverOsHandoff->PciRomSize = (UINT64) PciIoDevice->PciIo.RomSize;\r
267 Status = gBS->AllocatePool (\r
268 EfiRuntimeServicesData,\r
269 (UINTN) DriverOsHandoff->PciRomSize,\r
270 (VOID **) &DriverOsHandoff->PciRomImage\r
271 );\r
272 if (EFI_ERROR (Status)) {\r
273 gBS->FreePool (NewDriverOsHandoffHeader);\r
274 return Status;\r
275 }\r
276\r
277 gBS->CopyMem (\r
278 DriverOsHandoff->PciRomImage,\r
279 PciIoDevice->PciIo.RomImage,\r
280 (UINTN) DriverOsHandoff->PciRomSize\r
281 );\r
282\r
283 Status = gBS->InstallConfigurationTable (&gEfiUgaIoProtocolGuid, NewDriverOsHandoffHeader);\r
284 if (EFI_ERROR (Status)) {\r
285 return Status;\r
286 }\r
287\r
288 if (DriverOsHandoffHeader != NULL) {\r
289 gBS->FreePool (DriverOsHandoffHeader);\r
290 }\r
406adcd1 291#endif\r
878ddf1f 292\r
293 return EFI_SUCCESS;\r
294}\r