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