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.
18 Option Rom Support for PCI Bus Driver
27 EFI_HANDLE ImageHandle
;
32 } EFI_PCI_ROM_IMAGE_MAPPING
;
34 static UINTN mNumberOfPciRomImages
= 0;
35 static UINTN mMaxNumberOfPciRomImages
= 0;
36 static EFI_PCI_ROM_IMAGE_MAPPING
*mRomImageTable
= NULL
;
38 static CHAR16 mHexDigit
[17] = L
"0123456789ABCDEF";
42 PciRomAddImageMapping (
43 IN EFI_HANDLE ImageHandle
,
51 EFI_PCI_ROM_IMAGE_MAPPING
*TempMapping
;
53 if (mNumberOfPciRomImages
>= mMaxNumberOfPciRomImages
) {
55 mMaxNumberOfPciRomImages
+= 0x20;
58 TempMapping
= AllocatePool (mMaxNumberOfPciRomImages
* sizeof (EFI_PCI_ROM_IMAGE_MAPPING
));
59 if (TempMapping
== NULL
) {
63 CopyMem (TempMapping
, mRomImageTable
, mNumberOfPciRomImages
* sizeof (EFI_PCI_ROM_IMAGE_MAPPING
));
65 if (mRomImageTable
!= NULL
) {
66 gBS
->FreePool (mRomImageTable
);
69 mRomImageTable
= TempMapping
;
72 mRomImageTable
[mNumberOfPciRomImages
].ImageHandle
= ImageHandle
;
73 mRomImageTable
[mNumberOfPciRomImages
].Seg
= Seg
;
74 mRomImageTable
[mNumberOfPciRomImages
].Bus
= Bus
;
75 mRomImageTable
[mNumberOfPciRomImages
].Dev
= Dev
;
76 mRomImageTable
[mNumberOfPciRomImages
].Func
= Func
;
77 mNumberOfPciRomImages
++;
89 for (; Digits
> 0; Digits
--, String
++) {
90 *String
= mHexDigit
[((Value
>> (4*(Digits
-1))) & 0x0f)];
95 PciRomLoadEfiDriversFromRomImage (
96 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
97 IN EFI_PCI_OPTION_ROM_DESCRIPTOR
*PciOptionRomDescriptor
105 ImageHandle The image handle.
106 SystemTable The system table.
109 EFI_SUCCESS - The command completed successfully
110 EFI_INVALID_PARAMETER - Command usage error
111 EFI_UNSUPPORTED - Protocols unsupported
112 EFI_OUT_OF_RESOURCES - Out of memory
113 Other value - Unknown error
120 EFI_PCI_EXPANSION_ROM_HEADER
*EfiRomHeader
;
121 PCI_DATA_STRUCTURE
*Pcir
;
126 EFI_HANDLE ImageHandle
;
128 EFI_STATUS retStatus
;
129 EFI_DEVICE_PATH_PROTOCOL
*FilePath
;
131 UINT32 DestinationSize
;
135 VOID
*DecompressedImageBuffer
;
137 EFI_DECOMPRESS_PROTOCOL
*Decompress
;
139 RomBar
= (VOID
*) (UINTN
) PciOptionRomDescriptor
->RomAddress
;
140 RomSize
= (UINTN
) PciOptionRomDescriptor
->RomLength
;
141 FileName
= L
"PciRom Seg=00000000 Bus=00 Dev=00 Func=00 Image=0000";
143 HexToString (&FileName
[11], PciOptionRomDescriptor
->Seg
, 8);
144 HexToString (&FileName
[24], PciOptionRomDescriptor
->Bus
, 2);
145 HexToString (&FileName
[31], PciOptionRomDescriptor
->Dev
, 2);
146 HexToString (&FileName
[39], PciOptionRomDescriptor
->Func
, 2);
149 retStatus
= EFI_NOT_FOUND
;
150 RomBarOffset
= (UINTN
) RomBar
;
154 EfiRomHeader
= (EFI_PCI_EXPANSION_ROM_HEADER
*) (UINTN
) RomBarOffset
;
156 if (EfiRomHeader
->Signature
!= 0xaa55) {
160 Pcir
= (PCI_DATA_STRUCTURE
*) (UINTN
) (RomBarOffset
+ EfiRomHeader
->PcirOffset
);
161 ImageSize
= Pcir
->ImageLength
* 512;
163 if ((Pcir
->CodeType
== PCI_CODE_TYPE_EFI_IMAGE
) &&
164 (EfiRomHeader
->EfiSignature
== EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE
) ) {
166 if ((EfiRomHeader
->EfiSubsystem
== EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
) ||
167 (EfiRomHeader
->EfiSubsystem
== EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
) ) {
169 ImageOffset
= EfiRomHeader
->EfiImageHeaderOffset
;
170 ImageSize
= EfiRomHeader
->InitializationSize
* 512;
172 ImageBuffer
= (VOID
*) (UINTN
) (RomBarOffset
+ ImageOffset
);
173 ImageLength
= ImageSize
- ImageOffset
;
174 DecompressedImageBuffer
= NULL
;
177 // decompress here if needed
180 if (EfiRomHeader
->CompressionType
> EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED
) {
184 if (EfiRomHeader
->CompressionType
== EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED
) {
185 Status
= gBS
->LocateProtocol (&gEfiDecompressProtocolGuid
, NULL
, (VOID
**) &Decompress
);
186 if (EFI_ERROR (Status
)) {
190 Status
= Decompress
->GetInfo (
197 if (!EFI_ERROR (Status
)) {
198 DecompressedImageBuffer
= NULL
;
199 DecompressedImageBuffer
= AllocatePool (DestinationSize
);
200 if (DecompressedImageBuffer
!= NULL
) {
201 Scratch
= AllocatePool (ScratchSize
);
202 if (Scratch
!= NULL
) {
203 Status
= Decompress
->Decompress (
207 DecompressedImageBuffer
,
212 if (!EFI_ERROR (Status
)) {
213 ImageBuffer
= DecompressedImageBuffer
;
214 ImageLength
= DestinationSize
;
218 gBS
->FreePool (Scratch
);
228 // load image and start image
231 HexToString (&FileName
[48], ImageIndex
, 4);
232 FilePath
= FileDevicePath (NULL
, FileName
);
234 Status
= gBS
->LoadImage (
242 if (!EFI_ERROR (Status
)) {
243 Status
= gBS
->StartImage (ImageHandle
, NULL
, NULL
);
244 if (!EFI_ERROR (Status
)) {
245 PciRomAddImageMapping (
247 PciOptionRomDescriptor
->Seg
,
248 PciOptionRomDescriptor
->Bus
,
249 PciOptionRomDescriptor
->Dev
,
250 PciOptionRomDescriptor
->Func
255 if (FilePath
!= NULL
) {
256 gBS
->FreePool (FilePath
);
260 if (DecompressedImageBuffer
!= NULL
) {
261 gBS
->FreePool (DecompressedImageBuffer
);
267 RomBarOffset
= RomBarOffset
+ ImageSize
;
269 } while (((Pcir
->Indicator
& 0x80) == 0x00) && ((RomBarOffset
- (UINTN
) RomBar
) < RomSize
));
275 PciRomLoadEfiDriversFromOptionRomTable (
276 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
277 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
290 EFI_PCI_OPTION_ROM_TABLE
*PciOptionRomTable
;
291 EFI_PCI_OPTION_ROM_DESCRIPTOR
*PciOptionRomDescriptor
;
293 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptors
;
297 Status
= EfiGetSystemConfigurationTable (&gEfiPciOptionRomTableGuid
, (VOID
**) &PciOptionRomTable
);
298 if (EFI_ERROR (Status
)) {
299 return EFI_NOT_FOUND
;
302 Status
= EFI_NOT_FOUND
;
304 for (Index
= 0; Index
< PciOptionRomTable
->PciOptionRomCount
; Index
++) {
305 PciOptionRomDescriptor
= &PciOptionRomTable
->PciOptionRomDescriptors
[Index
];
306 if (!PciOptionRomDescriptor
->DontLoadEfiRom
) {
307 if (PciOptionRomDescriptor
->Seg
== PciRootBridgeIo
->SegmentNumber
) {
308 Status
= PciRootBridgeIo
->Configuration (PciRootBridgeIo
, (VOID
**) &Descriptors
);
309 if (EFI_ERROR (Status
)) {
313 PciGetBusRange (Descriptors
, &MinBus
, &MaxBus
, NULL
);
314 if ((MinBus
<= PciOptionRomDescriptor
->Bus
) && (PciOptionRomDescriptor
->Bus
<= MaxBus
)) {
315 Status
= PciRomLoadEfiDriversFromRomImage (This
, PciOptionRomDescriptor
);
316 PciOptionRomDescriptor
->DontLoadEfiRom
|= 2;
326 PciRomGetRomResourceFromPciOptionRomTable (
327 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
328 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
,
329 PCI_IO_DEVICE
*PciIoDevice
342 EFI_PCI_OPTION_ROM_TABLE
*PciOptionRomTable
;
343 EFI_PCI_OPTION_ROM_DESCRIPTOR
*PciOptionRomDescriptor
;
346 Status
= EfiGetSystemConfigurationTable (&gEfiPciOptionRomTableGuid
, (VOID
**) &PciOptionRomTable
);
347 if (EFI_ERROR (Status
)) {
348 return EFI_NOT_FOUND
;
351 for (Index
= 0; Index
< PciOptionRomTable
->PciOptionRomCount
; Index
++) {
352 PciOptionRomDescriptor
= &PciOptionRomTable
->PciOptionRomDescriptors
[Index
];
353 if (PciOptionRomDescriptor
->Seg
== PciRootBridgeIo
->SegmentNumber
&&
354 PciOptionRomDescriptor
->Bus
== PciIoDevice
->BusNumber
&&
355 PciOptionRomDescriptor
->Dev
== PciIoDevice
->DeviceNumber
&&
356 PciOptionRomDescriptor
->Func
== PciIoDevice
->FunctionNumber
) {
358 PciIoDevice
->PciIo
.RomImage
= (VOID
*) (UINTN
) PciOptionRomDescriptor
->RomAddress
;
359 PciIoDevice
->PciIo
.RomSize
= (UINTN
) PciOptionRomDescriptor
->RomLength
;
363 for (Index
= 0; Index
< mNumberOfPciRomImages
; Index
++) {
364 if (mRomImageTable
[Index
].Seg
== PciRootBridgeIo
->SegmentNumber
&&
365 mRomImageTable
[Index
].Bus
== PciIoDevice
->BusNumber
&&
366 mRomImageTable
[Index
].Dev
== PciIoDevice
->DeviceNumber
&&
367 mRomImageTable
[Index
].Func
== PciIoDevice
->FunctionNumber
) {
369 AddDriver (PciIoDevice
, mRomImageTable
[Index
].ImageHandle
);