3 Copyright (c) 2005 - 2007, 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
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.
29 IN
struct _EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL
*This
,
30 IN OUT EFI_HANDLE
*DriverImageHandle
36 InitializePciDriverOverrideInstance (
37 PCI_IO_DEVICE
*PciIoDevice
43 Initializes a PCI Driver Override Instance
54 PciIoDevice
->PciDriverOverride
.GetDriver
= GetDriver
;
61 IN EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL
*This
,
62 IN OUT EFI_HANDLE
*DriverImageHandle
68 Get a overriding driver image
78 PCI_IO_DEVICE
*PciIoDevice
;
79 LIST_ENTRY
*CurrentLink
;
80 PCI_DRIVER_OVERRIDE_LIST
*Node
;
82 PciIoDevice
= PCI_IO_DEVICE_FROM_PCI_DRIVER_OVERRIDE_THIS (This
);
84 CurrentLink
= PciIoDevice
->OptionRomDriverList
.ForwardLink
;
86 while (CurrentLink
&& CurrentLink
!= &PciIoDevice
->OptionRomDriverList
) {
88 Node
= DRIVER_OVERRIDE_FROM_LINK (CurrentLink
);
90 if (*DriverImageHandle
== NULL
) {
92 *DriverImageHandle
= Node
->DriverImageHandle
;
96 if (*DriverImageHandle
== Node
->DriverImageHandle
) {
98 if (CurrentLink
->ForwardLink
== &PciIoDevice
->OptionRomDriverList
||
99 CurrentLink
->ForwardLink
== NULL
) {
100 return EFI_NOT_FOUND
;
106 Node
= DRIVER_OVERRIDE_FROM_LINK (CurrentLink
->ForwardLink
);
107 *DriverImageHandle
= Node
->DriverImageHandle
;
111 CurrentLink
= CurrentLink
->ForwardLink
;
114 return EFI_INVALID_PARAMETER
;
119 IN PCI_IO_DEVICE
*PciIoDevice
,
120 IN EFI_HANDLE DriverImageHandle
126 Add a overriding driver image
138 EFI_IMAGE_DOS_HEADER
*DosHdr
;
139 EFI_IMAGE_NT_HEADERS
*PeHdr
;
140 EFI_LOADED_IMAGE_PROTOCOL
*LoadedImage
;
141 PCI_DRIVER_OVERRIDE_LIST
*Node
;
142 #if (EFI_SPECIFICATION_VERSION < 0x00020000)
143 EFI_DRIVER_OS_HANDOFF_HEADER
*DriverOsHandoffHeader
;
144 EFI_DRIVER_OS_HANDOFF_HEADER
*NewDriverOsHandoffHeader
;
145 EFI_DRIVER_OS_HANDOFF
*DriverOsHandoff
;
146 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
147 EFI_HANDLE DeviceHandle
;
148 UINTN NumberOfEntries
;
153 Status
= gBS
->HandleProtocol (DriverImageHandle
, &gEfiLoadedImageProtocolGuid
, (VOID
**) &LoadedImage
);
154 if (EFI_ERROR (Status
)) {
158 Node
= AllocatePool (sizeof (PCI_DRIVER_OVERRIDE_LIST
));
160 return EFI_OUT_OF_RESOURCES
;
163 Node
->Signature
= DRIVER_OVERRIDE_SIGNATURE
;
164 Node
->DriverImageHandle
= DriverImageHandle
;
166 InsertTailList (&PciIoDevice
->OptionRomDriverList
, &(Node
->Link
));
168 PciIoDevice
->BusOverride
= TRUE
;
170 DosHdr
= (EFI_IMAGE_DOS_HEADER
*) LoadedImage
->ImageBase
;
171 if (DosHdr
->e_magic
!= EFI_IMAGE_DOS_SIGNATURE
) {
175 PeHdr
= (EFI_IMAGE_NT_HEADERS
*) ((UINTN
) LoadedImage
->ImageBase
+ DosHdr
->e_lfanew
);
177 if (PeHdr
->FileHeader
.Machine
!= EFI_IMAGE_MACHINE_EBC
) {
181 #if (EFI_SPECIFICATION_VERSION < 0x00020000)
182 DriverOsHandoffHeader
= NULL
;
183 Status
= EfiLibGetSystemConfigurationTable (&gEfiUgaIoProtocolGuid
, (VOID
**) &DriverOsHandoffHeader
);
184 if (!EFI_ERROR (Status
) && DriverOsHandoffHeader
!= NULL
) {
185 for (Index
= 0; Index
< DriverOsHandoffHeader
->NumberOfEntries
; Index
++) {
186 DriverOsHandoff
= (EFI_DRIVER_OS_HANDOFF
*)((UINTN
)(DriverOsHandoffHeader
) +
187 DriverOsHandoffHeader
->HeaderSize
+
188 Index
* DriverOsHandoffHeader
->SizeOfEntries
);
189 DevicePath
= DriverOsHandoff
->DevicePath
;
190 Status
= gBS
->LocateDevicePath (&gEfiDevicePathProtocolGuid
, &DevicePath
, &DeviceHandle
);
191 if (!EFI_ERROR (Status
) && DeviceHandle
!= NULL
&& IsDevicePathEnd (DevicePath
)) {
192 if (DeviceHandle
== PciIoDevice
->Handle
) {
198 NumberOfEntries
= DriverOsHandoffHeader
->NumberOfEntries
+ 1;
203 Status
= gBS
->AllocatePool (
204 EfiRuntimeServicesData
,
205 sizeof (EFI_DRIVER_OS_HANDOFF_HEADER
) + NumberOfEntries
* sizeof (EFI_DRIVER_OS_HANDOFF
),
206 (VOID
**) &NewDriverOsHandoffHeader
208 if (EFI_ERROR (Status
)) {
212 if (DriverOsHandoffHeader
== NULL
) {
213 NewDriverOsHandoffHeader
->Version
= 0;
214 NewDriverOsHandoffHeader
->HeaderSize
= sizeof (EFI_DRIVER_OS_HANDOFF_HEADER
);
215 NewDriverOsHandoffHeader
->SizeOfEntries
= sizeof (EFI_DRIVER_OS_HANDOFF
);
216 NewDriverOsHandoffHeader
->NumberOfEntries
= (UINT32
) NumberOfEntries
;
219 NewDriverOsHandoffHeader
,
220 DriverOsHandoffHeader
,
221 DriverOsHandoffHeader
->HeaderSize
+ (NumberOfEntries
- 1) * DriverOsHandoffHeader
->SizeOfEntries
223 NewDriverOsHandoffHeader
->NumberOfEntries
= (UINT32
) NumberOfEntries
;
226 DriverOsHandoff
= (EFI_DRIVER_OS_HANDOFF
*)((UINTN
)NewDriverOsHandoffHeader
+
227 NewDriverOsHandoffHeader
->HeaderSize
+
228 (NumberOfEntries
- 1) * NewDriverOsHandoffHeader
->SizeOfEntries
);
231 // Fill in the EFI_DRIVER_OS_HANDOFF structure
233 DriverOsHandoff
->Type
= EfiUgaDriverFromPciRom
;
236 // Compute the size of the device path
238 Size
= EfiDevicePathSize (PciIoDevice
->DevicePath
);
240 DriverOsHandoff
->DevicePath
= NULL
;
244 // Allocate space for duplicate device path
246 Status
= gBS
->AllocatePool (
247 EfiRuntimeServicesData
,
249 (VOID
**) &DriverOsHandoff
->DevicePath
251 if (EFI_ERROR (Status
)) {
252 gBS
->FreePool (NewDriverOsHandoffHeader
);
257 // Make copy of device path
259 CopyMem (DriverOsHandoff
->DevicePath
, PciIoDevice
->DevicePath
, Size
);
262 DriverOsHandoff
->PciRomSize
= (UINT64
) PciIoDevice
->PciIo
.RomSize
;
263 Status
= gBS
->AllocatePool (
264 EfiRuntimeServicesData
,
265 (UINTN
) DriverOsHandoff
->PciRomSize
,
266 (VOID
**) &DriverOsHandoff
->PciRomImage
268 if (EFI_ERROR (Status
)) {
269 gBS
->FreePool (NewDriverOsHandoffHeader
);
274 DriverOsHandoff
->PciRomImage
,
275 PciIoDevice
->PciIo
.RomImage
,
276 (UINTN
) DriverOsHandoff
->PciRomSize
279 Status
= gBS
->InstallConfigurationTable (&gEfiUgaIoProtocolGuid
, NewDriverOsHandoffHeader
);
280 if (EFI_ERROR (Status
)) {
284 if (DriverOsHandoffHeader
!= NULL
) {
285 gBS
->FreePool (DriverOsHandoffHeader
);