3 Copyright (c) 2005 - 2012, Intel Corporation. All rights reserved.<BR>
4 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.
18 Option Rom Support for PCI Bus Driver
27 EFI_HANDLE ImageHandle
;
32 } EFI_PCI_ROM_IMAGE_MAPPING
;
34 UINTN mNumberOfPciRomImages
= 0;
35 UINTN mMaxNumberOfPciRomImages
= 0;
36 EFI_PCI_ROM_IMAGE_MAPPING
*mRomImageTable
= NULL
;
38 CHAR16 mHexDigit
[17] = L
"0123456789ABCDEF";
41 PciRomAddImageMapping (
42 IN EFI_HANDLE ImageHandle
,
50 EFI_PCI_ROM_IMAGE_MAPPING
*TempMapping
;
52 if (mNumberOfPciRomImages
>= mMaxNumberOfPciRomImages
) {
54 mMaxNumberOfPciRomImages
+= 0x20;
57 TempMapping
= AllocatePool (mMaxNumberOfPciRomImages
* sizeof (EFI_PCI_ROM_IMAGE_MAPPING
));
58 if (TempMapping
== NULL
) {
62 CopyMem (TempMapping
, mRomImageTable
, mNumberOfPciRomImages
* sizeof (EFI_PCI_ROM_IMAGE_MAPPING
));
64 if (mRomImageTable
!= NULL
) {
65 gBS
->FreePool (mRomImageTable
);
68 mRomImageTable
= TempMapping
;
71 mRomImageTable
[mNumberOfPciRomImages
].ImageHandle
= ImageHandle
;
72 mRomImageTable
[mNumberOfPciRomImages
].Seg
= Seg
;
73 mRomImageTable
[mNumberOfPciRomImages
].Bus
= Bus
;
74 mRomImageTable
[mNumberOfPciRomImages
].Dev
= Dev
;
75 mRomImageTable
[mNumberOfPciRomImages
].Func
= Func
;
76 mNumberOfPciRomImages
++;
87 for (; Digits
> 0; Digits
--, String
++) {
88 *String
= mHexDigit
[((Value
>> (4*(Digits
-1))) & 0x0f)];
93 PciRomLoadEfiDriversFromRomImage (
94 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
95 IN EFI_PCI_OPTION_ROM_DESCRIPTOR
*PciOptionRomDescriptor
103 ImageHandle The image handle.
104 SystemTable The system table.
107 EFI_SUCCESS - The command completed successfully
108 EFI_INVALID_PARAMETER - Command usage error
109 EFI_UNSUPPORTED - Protocols unsupported
110 EFI_OUT_OF_RESOURCES - Out of memory
111 Other value - Unknown error
118 EFI_PCI_EXPANSION_ROM_HEADER
*EfiRomHeader
;
119 PCI_DATA_STRUCTURE
*Pcir
;
124 EFI_HANDLE ImageHandle
;
126 EFI_STATUS retStatus
;
127 EFI_DEVICE_PATH_PROTOCOL
*FilePath
;
129 UINT32 DestinationSize
;
133 VOID
*DecompressedImageBuffer
;
135 EFI_DECOMPRESS_PROTOCOL
*Decompress
;
136 UINT32 InitializationSize
;
138 RomBar
= (VOID
*) (UINTN
) PciOptionRomDescriptor
->RomAddress
;
139 RomSize
= (UINTN
) PciOptionRomDescriptor
->RomLength
;
140 FileName
= L
"PciRom Seg=00000000 Bus=00 Dev=00 Func=00 Image=0000";
142 HexToString (&FileName
[11], PciOptionRomDescriptor
->Seg
, 8);
143 HexToString (&FileName
[24], PciOptionRomDescriptor
->Bus
, 2);
144 HexToString (&FileName
[31], PciOptionRomDescriptor
->Dev
, 2);
145 HexToString (&FileName
[39], PciOptionRomDescriptor
->Func
, 2);
148 retStatus
= EFI_NOT_FOUND
;
149 RomBarOffset
= (UINTN
) RomBar
;
153 EfiRomHeader
= (EFI_PCI_EXPANSION_ROM_HEADER
*) (UINTN
) RomBarOffset
;
156 if (EfiRomHeader
->Signature
!= PCI_EXPANSION_ROM_HEADER_SIGNATURE
) {
161 // If the pointer to the PCI Data Structure is invalid, no further images can be located.
162 // The PCI Data Structure must be DWORD aligned.
164 if (EfiRomHeader
->PcirOffset
== 0 ||
165 (EfiRomHeader
->PcirOffset
& 3) != 0 ||
166 RomBarOffset
- (UINTN
)RomBar
+ EfiRomHeader
->PcirOffset
+ sizeof (PCI_DATA_STRUCTURE
) > RomSize
) {
169 Pcir
= (PCI_DATA_STRUCTURE
*) (UINTN
) (RomBarOffset
+ EfiRomHeader
->PcirOffset
);
171 // If a valid signature is not present in the PCI Data Structure, no further images can be located.
173 if (Pcir
->Signature
!= PCI_DATA_STRUCTURE_SIGNATURE
) {
176 ImageSize
= Pcir
->ImageLength
* 512;
177 if (RomBarOffset
- (UINTN
)RomBar
+ ImageSize
> RomSize
) {
181 if ((Pcir
->CodeType
== PCI_CODE_TYPE_EFI_IMAGE
) &&
182 (EfiRomHeader
->EfiSignature
== EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE
) &&
183 ((EfiRomHeader
->EfiSubsystem
== EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
) ||
184 (EfiRomHeader
->EfiSubsystem
== EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
))) {
186 ImageOffset
= EfiRomHeader
->EfiImageHeaderOffset
;
187 InitializationSize
= EfiRomHeader
->InitializationSize
* 512;
189 if (InitializationSize
<= ImageSize
&& ImageOffset
< InitializationSize
) {
191 ImageBuffer
= (VOID
*) (UINTN
) (RomBarOffset
+ ImageOffset
);
192 ImageLength
= InitializationSize
- ImageOffset
;
193 DecompressedImageBuffer
= NULL
;
196 // decompress here if needed
199 if (EfiRomHeader
->CompressionType
> EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED
) {
203 if (EfiRomHeader
->CompressionType
== EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED
) {
204 Status
= gBS
->LocateProtocol (&gEfiDecompressProtocolGuid
, NULL
, (VOID
**) &Decompress
);
205 if (EFI_ERROR (Status
)) {
209 Status
= Decompress
->GetInfo (
216 if (!EFI_ERROR (Status
)) {
217 DecompressedImageBuffer
= NULL
;
218 DecompressedImageBuffer
= AllocatePool (DestinationSize
);
219 if (DecompressedImageBuffer
!= NULL
) {
220 Scratch
= AllocatePool (ScratchSize
);
221 if (Scratch
!= NULL
) {
222 Status
= Decompress
->Decompress (
226 DecompressedImageBuffer
,
231 if (!EFI_ERROR (Status
)) {
232 ImageBuffer
= DecompressedImageBuffer
;
233 ImageLength
= DestinationSize
;
237 gBS
->FreePool (Scratch
);
247 // load image and start image
250 HexToString (&FileName
[48], ImageIndex
, 4);
251 FilePath
= FileDevicePath (NULL
, FileName
);
253 Status
= gBS
->LoadImage (
261 if (!EFI_ERROR (Status
)) {
262 Status
= gBS
->StartImage (ImageHandle
, NULL
, NULL
);
263 if (!EFI_ERROR (Status
)) {
264 PciRomAddImageMapping (
266 PciOptionRomDescriptor
->Seg
,
267 PciOptionRomDescriptor
->Bus
,
268 PciOptionRomDescriptor
->Dev
,
269 PciOptionRomDescriptor
->Func
274 if (FilePath
!= NULL
) {
275 gBS
->FreePool (FilePath
);
279 if (DecompressedImageBuffer
!= NULL
) {
280 gBS
->FreePool (DecompressedImageBuffer
);
286 RomBarOffset
= RomBarOffset
+ ImageSize
;
288 } while (((Pcir
->Indicator
& 0x80) == 0x00) && ((RomBarOffset
- (UINTN
) RomBar
) < RomSize
));
294 PciRomLoadEfiDriversFromOptionRomTable (
295 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
296 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
309 EFI_PCI_OPTION_ROM_TABLE
*PciOptionRomTable
;
310 EFI_PCI_OPTION_ROM_DESCRIPTOR
*PciOptionRomDescriptor
;
312 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptors
;
316 Status
= EfiGetSystemConfigurationTable (&gEfiPciOptionRomTableGuid
, (VOID
**) &PciOptionRomTable
);
317 if (EFI_ERROR (Status
)) {
318 return EFI_NOT_FOUND
;
321 Status
= EFI_NOT_FOUND
;
323 for (Index
= 0; Index
< PciOptionRomTable
->PciOptionRomCount
; Index
++) {
324 PciOptionRomDescriptor
= &PciOptionRomTable
->PciOptionRomDescriptors
[Index
];
325 if (!PciOptionRomDescriptor
->DontLoadEfiRom
) {
326 if (PciOptionRomDescriptor
->Seg
== PciRootBridgeIo
->SegmentNumber
) {
327 Status
= PciRootBridgeIo
->Configuration (PciRootBridgeIo
, (VOID
**) &Descriptors
);
328 if (EFI_ERROR (Status
)) {
332 PciGetBusRange (&Descriptors
, &MinBus
, &MaxBus
, NULL
);
333 if ((MinBus
<= PciOptionRomDescriptor
->Bus
) && (PciOptionRomDescriptor
->Bus
<= MaxBus
)) {
334 Status
= PciRomLoadEfiDriversFromRomImage (This
, PciOptionRomDescriptor
);
335 PciOptionRomDescriptor
->DontLoadEfiRom
|= 2;
345 PciRomGetRomResourceFromPciOptionRomTable (
346 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
347 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
,
348 PCI_IO_DEVICE
*PciIoDevice
361 EFI_PCI_OPTION_ROM_TABLE
*PciOptionRomTable
;
362 EFI_PCI_OPTION_ROM_DESCRIPTOR
*PciOptionRomDescriptor
;
365 Status
= EfiGetSystemConfigurationTable (&gEfiPciOptionRomTableGuid
, (VOID
**) &PciOptionRomTable
);
366 if (EFI_ERROR (Status
)) {
367 return EFI_NOT_FOUND
;
370 for (Index
= 0; Index
< PciOptionRomTable
->PciOptionRomCount
; Index
++) {
371 PciOptionRomDescriptor
= &PciOptionRomTable
->PciOptionRomDescriptors
[Index
];
372 if (PciOptionRomDescriptor
->Seg
== PciRootBridgeIo
->SegmentNumber
&&
373 PciOptionRomDescriptor
->Bus
== PciIoDevice
->BusNumber
&&
374 PciOptionRomDescriptor
->Dev
== PciIoDevice
->DeviceNumber
&&
375 PciOptionRomDescriptor
->Func
== PciIoDevice
->FunctionNumber
) {
377 PciIoDevice
->PciIo
.RomImage
= (VOID
*) (UINTN
) PciOptionRomDescriptor
->RomAddress
;
378 PciIoDevice
->PciIo
.RomSize
= (UINTN
) PciOptionRomDescriptor
->RomLength
;
382 for (Index
= 0; Index
< mNumberOfPciRomImages
; Index
++) {
383 if (mRomImageTable
[Index
].Seg
== PciRootBridgeIo
->SegmentNumber
&&
384 mRomImageTable
[Index
].Bus
== PciIoDevice
->BusNumber
&&
385 mRomImageTable
[Index
].Dev
== PciIoDevice
->DeviceNumber
&&
386 mRomImageTable
[Index
].Func
== PciIoDevice
->FunctionNumber
) {
388 AddDriver (PciIoDevice
, mRomImageTable
[Index
].ImageHandle
);