3 Copyright (c) 2005 - 2007, 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
;
137 RomBar
= (VOID
*) (UINTN
) PciOptionRomDescriptor
->RomAddress
;
138 RomSize
= (UINTN
) PciOptionRomDescriptor
->RomLength
;
139 FileName
= L
"PciRom Seg=00000000 Bus=00 Dev=00 Func=00 Image=0000";
141 HexToString (&FileName
[11], PciOptionRomDescriptor
->Seg
, 8);
142 HexToString (&FileName
[24], PciOptionRomDescriptor
->Bus
, 2);
143 HexToString (&FileName
[31], PciOptionRomDescriptor
->Dev
, 2);
144 HexToString (&FileName
[39], PciOptionRomDescriptor
->Func
, 2);
147 retStatus
= EFI_NOT_FOUND
;
148 RomBarOffset
= (UINTN
) RomBar
;
152 EfiRomHeader
= (EFI_PCI_EXPANSION_ROM_HEADER
*) (UINTN
) RomBarOffset
;
154 if (EfiRomHeader
->Signature
!= 0xaa55) {
158 Pcir
= (PCI_DATA_STRUCTURE
*) (UINTN
) (RomBarOffset
+ EfiRomHeader
->PcirOffset
);
159 ImageSize
= Pcir
->ImageLength
* 512;
161 if ((Pcir
->CodeType
== PCI_CODE_TYPE_EFI_IMAGE
) &&
162 (EfiRomHeader
->EfiSignature
== EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE
) ) {
164 if ((EfiRomHeader
->EfiSubsystem
== EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
) ||
165 (EfiRomHeader
->EfiSubsystem
== EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
) ) {
167 ImageOffset
= EfiRomHeader
->EfiImageHeaderOffset
;
168 ImageSize
= EfiRomHeader
->InitializationSize
* 512;
170 ImageBuffer
= (VOID
*) (UINTN
) (RomBarOffset
+ ImageOffset
);
171 ImageLength
= ImageSize
- ImageOffset
;
172 DecompressedImageBuffer
= NULL
;
175 // decompress here if needed
178 if (EfiRomHeader
->CompressionType
> EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED
) {
182 if (EfiRomHeader
->CompressionType
== EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED
) {
183 Status
= gBS
->LocateProtocol (&gEfiDecompressProtocolGuid
, NULL
, (VOID
**) &Decompress
);
184 if (EFI_ERROR (Status
)) {
188 Status
= Decompress
->GetInfo (
195 if (!EFI_ERROR (Status
)) {
196 DecompressedImageBuffer
= NULL
;
197 DecompressedImageBuffer
= AllocatePool (DestinationSize
);
198 if (DecompressedImageBuffer
!= NULL
) {
199 Scratch
= AllocatePool (ScratchSize
);
200 if (Scratch
!= NULL
) {
201 Status
= Decompress
->Decompress (
205 DecompressedImageBuffer
,
210 if (!EFI_ERROR (Status
)) {
211 ImageBuffer
= DecompressedImageBuffer
;
212 ImageLength
= DestinationSize
;
216 gBS
->FreePool (Scratch
);
226 // load image and start image
229 HexToString (&FileName
[48], ImageIndex
, 4);
230 FilePath
= FileDevicePath (NULL
, FileName
);
232 Status
= gBS
->LoadImage (
240 if (!EFI_ERROR (Status
)) {
241 Status
= gBS
->StartImage (ImageHandle
, NULL
, NULL
);
242 if (!EFI_ERROR (Status
)) {
243 PciRomAddImageMapping (
245 PciOptionRomDescriptor
->Seg
,
246 PciOptionRomDescriptor
->Bus
,
247 PciOptionRomDescriptor
->Dev
,
248 PciOptionRomDescriptor
->Func
253 if (FilePath
!= NULL
) {
254 gBS
->FreePool (FilePath
);
258 if (DecompressedImageBuffer
!= NULL
) {
259 gBS
->FreePool (DecompressedImageBuffer
);
265 RomBarOffset
= RomBarOffset
+ ImageSize
;
267 } while (((Pcir
->Indicator
& 0x80) == 0x00) && ((RomBarOffset
- (UINTN
) RomBar
) < RomSize
));
273 PciRomLoadEfiDriversFromOptionRomTable (
274 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
275 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
288 EFI_PCI_OPTION_ROM_TABLE
*PciOptionRomTable
;
289 EFI_PCI_OPTION_ROM_DESCRIPTOR
*PciOptionRomDescriptor
;
291 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptors
;
295 Status
= EfiGetSystemConfigurationTable (&gEfiPciOptionRomTableGuid
, (VOID
**) &PciOptionRomTable
);
296 if (EFI_ERROR (Status
)) {
297 return EFI_NOT_FOUND
;
300 Status
= EFI_NOT_FOUND
;
302 for (Index
= 0; Index
< PciOptionRomTable
->PciOptionRomCount
; Index
++) {
303 PciOptionRomDescriptor
= &PciOptionRomTable
->PciOptionRomDescriptors
[Index
];
304 if (!PciOptionRomDescriptor
->DontLoadEfiRom
) {
305 if (PciOptionRomDescriptor
->Seg
== PciRootBridgeIo
->SegmentNumber
) {
306 Status
= PciRootBridgeIo
->Configuration (PciRootBridgeIo
, (VOID
**) &Descriptors
);
307 if (EFI_ERROR (Status
)) {
311 PciGetBusRange (&Descriptors
, &MinBus
, &MaxBus
, NULL
);
312 if ((MinBus
<= PciOptionRomDescriptor
->Bus
) && (PciOptionRomDescriptor
->Bus
<= MaxBus
)) {
313 Status
= PciRomLoadEfiDriversFromRomImage (This
, PciOptionRomDescriptor
);
314 PciOptionRomDescriptor
->DontLoadEfiRom
|= 2;
324 PciRomGetRomResourceFromPciOptionRomTable (
325 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
326 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
,
327 PCI_IO_DEVICE
*PciIoDevice
340 EFI_PCI_OPTION_ROM_TABLE
*PciOptionRomTable
;
341 EFI_PCI_OPTION_ROM_DESCRIPTOR
*PciOptionRomDescriptor
;
344 Status
= EfiGetSystemConfigurationTable (&gEfiPciOptionRomTableGuid
, (VOID
**) &PciOptionRomTable
);
345 if (EFI_ERROR (Status
)) {
346 return EFI_NOT_FOUND
;
349 for (Index
= 0; Index
< PciOptionRomTable
->PciOptionRomCount
; Index
++) {
350 PciOptionRomDescriptor
= &PciOptionRomTable
->PciOptionRomDescriptors
[Index
];
351 if (PciOptionRomDescriptor
->Seg
== PciRootBridgeIo
->SegmentNumber
&&
352 PciOptionRomDescriptor
->Bus
== PciIoDevice
->BusNumber
&&
353 PciOptionRomDescriptor
->Dev
== PciIoDevice
->DeviceNumber
&&
354 PciOptionRomDescriptor
->Func
== PciIoDevice
->FunctionNumber
) {
356 PciIoDevice
->PciIo
.RomImage
= (VOID
*) (UINTN
) PciOptionRomDescriptor
->RomAddress
;
357 PciIoDevice
->PciIo
.RomSize
= (UINTN
) PciOptionRomDescriptor
->RomLength
;
361 for (Index
= 0; Index
< mNumberOfPciRomImages
; Index
++) {
362 if (mRomImageTable
[Index
].Seg
== PciRootBridgeIo
->SegmentNumber
&&
363 mRomImageTable
[Index
].Bus
== PciIoDevice
->BusNumber
&&
364 mRomImageTable
[Index
].Dev
== PciIoDevice
->DeviceNumber
&&
365 mRomImageTable
[Index
].Func
== PciIoDevice
->FunctionNumber
) {
367 AddDriver (PciIoDevice
, mRomImageTable
[Index
].ImageHandle
);