]> git.proxmox.com Git - mirror_edk2.git/blame - EdkModulePkg/Bus/Pci/PciBus/Dxe/PciDriverOverride.c
Initial import.
[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
142 EFI_IMAGE_DOS_HEADER *DosHdr;\r
143 EFI_IMAGE_NT_HEADERS *PeHdr;\r
144 EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;\r
145 PCI_DRIVER_OVERRIDE_LIST *Node;\r
146 EFI_DRIVER_OS_HANDOFF_HEADER *DriverOsHandoffHeader;\r
147 EFI_DRIVER_OS_HANDOFF_HEADER *NewDriverOsHandoffHeader;\r
148 EFI_DRIVER_OS_HANDOFF *DriverOsHandoff;\r
149 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
150 EFI_HANDLE DeviceHandle;\r
151 UINTN NumberOfEntries;\r
152 UINTN Size;\r
153 UINTN Index;\r
154\r
155 Status = gBS->HandleProtocol (DriverImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **) &LoadedImage);\r
156 if (EFI_ERROR (Status)) {\r
157 return Status;\r
158 }\r
159\r
160 Node = AllocatePool (sizeof (PCI_DRIVER_OVERRIDE_LIST));\r
161 if (Node == NULL) {\r
162 return EFI_OUT_OF_RESOURCES;\r
163 }\r
164\r
165 Node->Signature = DRIVER_OVERRIDE_SIGNATURE;\r
166 Node->DriverImageHandle = DriverImageHandle;\r
167\r
168 InsertTailList (&PciIoDevice->OptionRomDriverList, &(Node->Link));\r
169\r
170 PciIoDevice->BusOverride = TRUE;\r
171\r
172 DosHdr = (EFI_IMAGE_DOS_HEADER *) LoadedImage->ImageBase;\r
173 if (DosHdr->e_magic != EFI_IMAGE_DOS_SIGNATURE) {\r
174 return EFI_SUCCESS;\r
175 }\r
176\r
177 PeHdr = (EFI_IMAGE_NT_HEADERS *) ((UINTN) LoadedImage->ImageBase + DosHdr->e_lfanew);\r
178\r
179 if (PeHdr->FileHeader.Machine != EFI_IMAGE_MACHINE_EBC) {\r
180 return EFI_SUCCESS;\r
181 }\r
182\r
183 DriverOsHandoffHeader = NULL;\r
184 Status = EfiGetSystemConfigurationTable (&gEfiUgaIoProtocolGuid, (VOID **) &DriverOsHandoffHeader);\r
185 if (!EFI_ERROR (Status) && DriverOsHandoffHeader != NULL) {\r
186 for (Index = 0; Index < DriverOsHandoffHeader->NumberOfEntries; Index++) {\r
187 DriverOsHandoff = (EFI_DRIVER_OS_HANDOFF *)((UINTN)(DriverOsHandoffHeader) + \r
188 DriverOsHandoffHeader->HeaderSize + \r
189 Index * DriverOsHandoffHeader->SizeOfEntries);\r
190 DevicePath = DriverOsHandoff->DevicePath;\r
191 Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &DevicePath, &DeviceHandle);\r
192 if (!EFI_ERROR (Status) && DeviceHandle != NULL && IsDevicePathEnd (DevicePath)) {\r
193 if (DeviceHandle == PciIoDevice->Handle) {\r
194 return EFI_SUCCESS;\r
195 }\r
196 }\r
197 }\r
198\r
199 NumberOfEntries = DriverOsHandoffHeader->NumberOfEntries + 1;\r
200 } else {\r
201 NumberOfEntries = 1;\r
202 }\r
203\r
204 Status = gBS->AllocatePool (\r
205 EfiRuntimeServicesData,\r
206 sizeof (EFI_DRIVER_OS_HANDOFF_HEADER) + NumberOfEntries * sizeof (EFI_DRIVER_OS_HANDOFF),\r
207 (VOID **) &NewDriverOsHandoffHeader\r
208 );\r
209 if (EFI_ERROR (Status)) {\r
210 return Status;\r
211 }\r
212\r
213 if (DriverOsHandoffHeader == NULL) {\r
214 NewDriverOsHandoffHeader->Version = 0;\r
215 NewDriverOsHandoffHeader->HeaderSize = sizeof (EFI_DRIVER_OS_HANDOFF_HEADER);\r
216 NewDriverOsHandoffHeader->SizeOfEntries = sizeof (EFI_DRIVER_OS_HANDOFF);\r
217 NewDriverOsHandoffHeader->NumberOfEntries = (UINT32) NumberOfEntries;\r
218 } else {\r
219 gBS->CopyMem (\r
220 NewDriverOsHandoffHeader,\r
221 DriverOsHandoffHeader,\r
222 DriverOsHandoffHeader->HeaderSize + (NumberOfEntries - 1) * DriverOsHandoffHeader->SizeOfEntries\r
223 );\r
224 NewDriverOsHandoffHeader->NumberOfEntries = (UINT32) NumberOfEntries;\r
225 }\r
226\r
227 DriverOsHandoff = (EFI_DRIVER_OS_HANDOFF *)((UINTN)NewDriverOsHandoffHeader + \r
228 NewDriverOsHandoffHeader->HeaderSize + \r
229 (NumberOfEntries - 1) * NewDriverOsHandoffHeader->SizeOfEntries);\r
230\r
231 //\r
232 // Fill in the EFI_DRIVER_OS_HANDOFF structure\r
233 //\r
234 DriverOsHandoff->Type = EfiUgaDriverFromPciRom;\r
235\r
236 //\r
237 // Compute the size of the device path\r
238 //\r
239 Size = GetDevicePathSize (PciIoDevice->DevicePath);\r
240 if (Size == 0) {\r
241 DriverOsHandoff->DevicePath = NULL;\r
242 } else {\r
243\r
244 //\r
245 // Allocate space for duplicate device path\r
246 //\r
247 Status = gBS->AllocatePool (\r
248 EfiRuntimeServicesData,\r
249 Size,\r
250 (VOID **) &DriverOsHandoff->DevicePath\r
251 );\r
252 if (EFI_ERROR (Status)) {\r
253 gBS->FreePool (NewDriverOsHandoffHeader);\r
254 return Status;\r
255 }\r
256\r
257 //\r
258 // Make copy of device path\r
259 //\r
260 CopyMem (DriverOsHandoff->DevicePath, PciIoDevice->DevicePath, Size);\r
261 }\r
262\r
263 DriverOsHandoff->PciRomSize = (UINT64) PciIoDevice->PciIo.RomSize;\r
264 Status = gBS->AllocatePool (\r
265 EfiRuntimeServicesData,\r
266 (UINTN) DriverOsHandoff->PciRomSize,\r
267 (VOID **) &DriverOsHandoff->PciRomImage\r
268 );\r
269 if (EFI_ERROR (Status)) {\r
270 gBS->FreePool (NewDriverOsHandoffHeader);\r
271 return Status;\r
272 }\r
273\r
274 gBS->CopyMem (\r
275 DriverOsHandoff->PciRomImage,\r
276 PciIoDevice->PciIo.RomImage,\r
277 (UINTN) DriverOsHandoff->PciRomSize\r
278 );\r
279\r
280 Status = gBS->InstallConfigurationTable (&gEfiUgaIoProtocolGuid, NewDriverOsHandoffHeader);\r
281 if (EFI_ERROR (Status)) {\r
282 return Status;\r
283 }\r
284\r
285 if (DriverOsHandoffHeader != NULL) {\r
286 gBS->FreePool (DriverOsHandoffHeader);\r
287 }\r
288\r
289 return EFI_SUCCESS;\r
290}\r