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.
29 IN PCI_IO_DEVICE
*PciDevice
,
37 IN PCI_IO_DEVICE
*PciIoDevice
56 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
58 Bus
= PciIoDevice
->BusNumber
;
59 Device
= PciIoDevice
->DeviceNumber
;
60 Function
= PciIoDevice
->FunctionNumber
;
62 PciRootBridgeIo
= PciIoDevice
->PciRootBridgeIo
;
65 // offset is 0x30 if is not ppb
71 RomBarIndex
= PCI_EXPANSION_ROM_BASE
;
73 if (IS_PCI_BRIDGE (&PciIoDevice
->Pci
)) {
81 RomBarIndex
= PCI_BRIDGE_ROMBAR
;
84 // the bit0 is 0 to prevent the enabling of the Rom address decoder
87 Address
= EFI_PCI_ADDRESS (Bus
, Device
, Function
, RomBarIndex
);
89 Status
= PciRootBridgeIo
->Pci
.Write (
96 if (EFI_ERROR (Status
)) {
103 Status
= PciRootBridgeIo
->Pci
.Read (
110 if (EFI_ERROR (Status
)) {
115 // Bits [1, 10] are reserved
117 AllOnes
&= 0xFFFFF800;
118 if ((AllOnes
== 0) || (AllOnes
== 0xFFFFF800)) {
119 return EFI_NOT_FOUND
;
122 DEBUG ((EFI_D_ERROR
, "PCIBUS: GetOpRomInfo: OPROM detected!\n"));
123 DEBUG ((EFI_D_ERROR
, "PCIBUS: GetOpRomInfo: B-%x, D-%x, F-%x\n", (UINTN
)Bus
, (UINTN
)Device
, (UINTN
)Function
));
125 PciIoDevice
->RomSize
= (UINT64
) ((~AllOnes
) + 1);
131 IN PCI_IO_DEVICE
*PciDevice
,
132 IN UINT64 ReservedMemoryBase
138 Load option rom image for specified PCI device
151 EFI_STATUS retStatus
;
154 PCI_EXPANSION_ROM_HEADER
*RomHeader
;
155 PCI_DATA_STRUCTURE
*RomPcir
;
158 UINT32 LegacyImageLength
;
162 RomSize
= PciDevice
->RomSize
;
170 // Get the RomBarIndex
176 RomBarIndex
= PCI_EXPANSION_ROM_BASE
;
177 if (IS_PCI_BRIDGE (&(PciDevice
->Pci
))) {
185 RomBarIndex
= PCI_BRIDGE_ROMBAR
;
188 // Allocate memory for Rom header and PCIR
190 RomHeader
= AllocatePool (sizeof (PCI_EXPANSION_ROM_HEADER
));
191 if (RomHeader
== NULL
) {
192 return EFI_OUT_OF_RESOURCES
;
195 RomPcir
= AllocatePool (sizeof (PCI_DATA_STRUCTURE
));
196 if (RomPcir
== NULL
) {
197 gBS
->FreePool (RomHeader
);
198 return EFI_OUT_OF_RESOURCES
;
201 RomBar
= (UINT32
)ReservedMemoryBase
;
206 RomDecode (PciDevice
, RomBarIndex
, RomBar
, TRUE
);
208 RomBarOffset
= RomBar
;
209 retStatus
= EFI_NOT_FOUND
;
211 LegacyImageLength
= 0;
214 PciDevice
->PciRootBridgeIo
->Mem
.Read (
215 PciDevice
->PciRootBridgeIo
,
218 sizeof (PCI_EXPANSION_ROM_HEADER
),
222 if (RomHeader
->Signature
!= PCI_EXPANSION_ROM_HEADER_SIGNATURE
) {
223 RomBarOffset
= RomBarOffset
+ 512;
227 RomImageSize
= RomImageSize
+ 512;
233 OffsetPcir
= RomHeader
->PcirOffset
;
235 // If the pointer to the PCI Data Structure is invalid, no further images can be located.
236 // The PCI Data Structure must be DWORD aligned.
238 if (OffsetPcir
== 0 ||
239 (OffsetPcir
& 3) != 0 ||
240 RomImageSize
+ OffsetPcir
+ sizeof (PCI_DATA_STRUCTURE
) > RomSize
) {
243 PciDevice
->PciRootBridgeIo
->Mem
.Read (
244 PciDevice
->PciRootBridgeIo
,
246 RomBarOffset
+ OffsetPcir
,
247 sizeof (PCI_DATA_STRUCTURE
),
251 // If a valid signature is not present in the PCI Data Structure, no further images can be located.
253 if (RomPcir
->Signature
!= PCI_DATA_STRUCTURE_SIGNATURE
) {
256 if (RomImageSize
+ RomPcir
->ImageLength
* 512 > RomSize
) {
259 if (RomPcir
->CodeType
== PCI_CODE_TYPE_PCAT_IMAGE
) {
260 CodeType
= PCI_CODE_TYPE_PCAT_IMAGE
;
261 LegacyImageLength
= ((UINT32
)((EFI_LEGACY_EXPANSION_ROM_HEADER
*)RomHeader
)->Size512
) * 512;
263 Indicator
= RomPcir
->Indicator
;
264 RomImageSize
= RomImageSize
+ RomPcir
->ImageLength
* 512;
265 RomBarOffset
= RomBarOffset
+ RomPcir
->ImageLength
* 512;
266 } while (((Indicator
& 0x80) == 0x00) && ((RomBarOffset
- RomBar
) < RomSize
));
269 // Some Legacy Cards do not report the correct ImageLength so used the maximum
270 // of the legacy length and the PCIR Image Length
272 if (CodeType
== PCI_CODE_TYPE_PCAT_IMAGE
) {
273 RomImageSize
= MAX (RomImageSize
, LegacyImageLength
);
276 if (RomImageSize
> 0) {
277 retStatus
= EFI_SUCCESS
;
278 Image
= AllocatePool ((UINT32
) RomImageSize
);
280 RomDecode (PciDevice
, RomBarIndex
, RomBar
, FALSE
);
281 gBS
->FreePool (RomHeader
);
282 gBS
->FreePool (RomPcir
);
283 return EFI_OUT_OF_RESOURCES
;
287 // Copy Rom image into memory
289 PciDevice
->PciRootBridgeIo
->Mem
.Read (
290 PciDevice
->PciRootBridgeIo
,
293 (UINT32
) RomImageSize
,
299 RomDecode (PciDevice
, RomBarIndex
, RomBar
, FALSE
);
301 PciDevice
->PciIo
.RomSize
= RomImageSize
;
302 PciDevice
->PciIo
.RomImage
= RomInMemory
;
305 // Free allocated memory
307 gBS
->FreePool (RomHeader
);
308 gBS
->FreePool (RomPcir
);
315 IN PCI_IO_DEVICE
*PciDevice
,
316 IN UINT8 RomBarIndex
,
334 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
336 PciRootBridgeIo
= PciDevice
->PciRootBridgeIo
;
338 Address
= EFI_PCI_ADDRESS (PciDevice
->BusNumber
, PciDevice
->DeviceNumber
, PciDevice
->FunctionNumber
, RomBarIndex
);
340 // set the Rom base address: now is hardcode
342 PciRootBridgeIo
->Pci
.Write(
350 // enable its decoder
352 Value32
= RomBar
| 0x1;
353 PciRootBridgeIo
->Pci
.Write(
361 //setting the memory space bit in the function's command register
363 Address
= EFI_PCI_ADDRESS (PciDevice
->BusNumber
, PciDevice
->DeviceNumber
, PciDevice
->FunctionNumber
, 0x04);
364 PciRootBridgeIo
->Pci
.Read(
371 CommandValue
= (UINT16
)(CommandValue
| 0x0002); //0x0003
372 PciRootBridgeIo
->Pci
.Write(
380 // disable rom decode
382 Address
= EFI_PCI_ADDRESS (PciDevice
->BusNumber
, PciDevice
->DeviceNumber
, PciDevice
->FunctionNumber
, RomBarIndex
);
383 Value32
= 0xfffffffe;
384 PciRootBridgeIo
->Pci
.Write(
398 PCI_IO_DEVICE
*PciDevice
404 Process the oprom image.
407 PciDevice A pointer to a pci device.
420 EFI_HANDLE ImageHandle
;
422 EFI_STATUS retStatus
;
424 UINT32 DestinationSize
;
428 VOID
*DecompressedImageBuffer
;
430 EFI_DECOMPRESS_PROTOCOL
*Decompress
;
431 EFI_PCI_EXPANSION_ROM_HEADER
*EfiRomHeader
;
432 PCI_DATA_STRUCTURE
*Pcir
;
433 UINT32 InitializationSize
;
438 // Get the Address of the Rom image
440 RomBar
= PciDevice
->PciIo
.RomImage
;
441 RomBarOffset
= (UINT8
*) RomBar
;
442 retStatus
= EFI_NOT_FOUND
;
444 if (RomBarOffset
== NULL
) {
447 ASSERT (((EFI_PCI_EXPANSION_ROM_HEADER
*) RomBarOffset
)->Signature
== PCI_EXPANSION_ROM_HEADER_SIGNATURE
);
450 EfiRomHeader
= (EFI_PCI_EXPANSION_ROM_HEADER
*) RomBarOffset
;
451 if (EfiRomHeader
->Signature
!= PCI_EXPANSION_ROM_HEADER_SIGNATURE
) {
452 RomBarOffset
= RomBarOffset
+ 512;
456 Pcir
= (PCI_DATA_STRUCTURE
*) (RomBarOffset
+ EfiRomHeader
->PcirOffset
);
457 ASSERT (Pcir
->Signature
== PCI_DATA_STRUCTURE_SIGNATURE
);
458 ImageSize
= (UINT32
) (Pcir
->ImageLength
* 512);
459 Indicator
= Pcir
->Indicator
;
461 if ((Pcir
->CodeType
== PCI_CODE_TYPE_EFI_IMAGE
) &&
462 (EfiRomHeader
->EfiSignature
== EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE
) &&
463 ((EfiRomHeader
->EfiSubsystem
== EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
) ||
464 (EfiRomHeader
->EfiSubsystem
== EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
))) {
466 ImageOffset
= EfiRomHeader
->EfiImageHeaderOffset
;
467 InitializationSize
= EfiRomHeader
->InitializationSize
* 512;
469 if (InitializationSize
<= ImageSize
&& ImageOffset
< InitializationSize
) {
471 ImageBuffer
= (VOID
*) (RomBarOffset
+ ImageOffset
);
472 ImageLength
= InitializationSize
- (UINT32
)ImageOffset
;
473 DecompressedImageBuffer
= NULL
;
476 // decompress here if needed
479 if (EfiRomHeader
->CompressionType
> EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED
) {
483 if (EfiRomHeader
->CompressionType
== EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED
) {
484 Status
= gBS
->LocateProtocol (&gEfiDecompressProtocolGuid
, NULL
, (VOID
**) &Decompress
);
485 if (EFI_ERROR (Status
)) {
489 Status
= Decompress
->GetInfo (
496 if (!EFI_ERROR (Status
)) {
497 DecompressedImageBuffer
= NULL
;
498 DecompressedImageBuffer
= AllocatePool (DestinationSize
);
499 if (DecompressedImageBuffer
!= NULL
) {
500 Scratch
= AllocatePool (ScratchSize
);
501 if (Scratch
!= NULL
) {
502 Status
= Decompress
->Decompress (
506 DecompressedImageBuffer
,
511 if (!EFI_ERROR (Status
)) {
512 ImageBuffer
= DecompressedImageBuffer
;
513 ImageLength
= DestinationSize
;
517 gBS
->FreePool (Scratch
);
526 // load image and start image
528 Status
= gBS
->LoadImage (
530 gPciBusDriverBinding
.DriverBindingHandle
,
536 if (!EFI_ERROR (Status
)) {
537 Status
= gBS
->StartImage (ImageHandle
, NULL
, NULL
);
538 if (!EFI_ERROR (Status
)) {
539 AddDriver (PciDevice
, ImageHandle
);
540 retStatus
= EFI_SUCCESS
;
545 RomBarOffset
= RomBarOffset
+ ImageSize
;
547 RomBarOffset
= RomBarOffset
+ ImageSize
;
550 RomBarOffset
= RomBarOffset
+ ImageSize
;
553 } while (((Indicator
& 0x80) == 0x00) && ((UINTN
) (RomBarOffset
- (UINT8
*) RomBar
) < PciDevice
->RomSize
));