3 Copyright (c) 2006, 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.
15 #include "PciResourceSupport.h"
17 #include <IndustryStandard/Pci23.h>
21 IN PCI_IO_DEVICE
*PciIoDevice
32 // TODO: PciIoDevice - add argument and description to function comment
33 // TODO: EFI_NOT_FOUND - add return value to function comment
34 // TODO: EFI_SUCCESS - add return value to function comment
43 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
45 Bus
= PciIoDevice
->BusNumber
;
46 Device
= PciIoDevice
->DeviceNumber
;
47 Function
= PciIoDevice
->FunctionNumber
;
49 PciRootBridgeIo
= PciIoDevice
->PciRootBridgeIo
;
52 // offset is 0x30 if is not ppb
58 RomBarIndex
= PCI_DEVICE_ROMBAR
;
60 if (IS_PCI_BRIDGE (&PciIoDevice
->Pci
)) {
68 RomBarIndex
= PCI_BRIDGE_ROMBAR
;
71 // the bit0 is 0 to prevent the enabling of the Rom address decoder
74 Address
= EFI_PCI_ADDRESS (Bus
, Device
, Function
, RomBarIndex
);
76 Status
= PciRootBridgeIoWrite (
84 if (EFI_ERROR (Status
)) {
91 Status
= PciRootBridgeIoRead (
99 if (EFI_ERROR (Status
)) {
103 // Bits [1, 10] are reserved
105 AllOnes
&= 0xFFFFF800;
106 if ((AllOnes
== 0) || (AllOnes
== 0xFFFFF800)) {
107 return EFI_NOT_FOUND
;
110 PciIoDevice
->RomSize
= (UINT64
) ((~AllOnes
) + 1);
116 IN PCI_IO_DEVICE
*PciDevice
,
123 Load option rom image for specified PCI device
130 // TODO: PciDevice - add argument and description to function comment
131 // TODO: RomBase - add argument and description to function comment
132 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
133 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
134 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
141 EFI_STATUS retStatus
;
144 PCI_EXPANSION_ROM_HEADER
*RomHeader
;
145 PCI_DATA_STRUCTURE
*RomPcir
;
151 RomSize
= PciDevice
->RomSize
;
159 // Get the RomBarIndex
165 RomBarIndex
= PCI_DEVICE_ROMBAR
;
166 if (IS_PCI_BRIDGE (&(PciDevice
->Pci
))) {
174 RomBarIndex
= PCI_BRIDGE_ROMBAR
;
177 // Allocate memory for Rom header and PCIR
179 RomHeader
= AllocatePool (sizeof (PCI_EXPANSION_ROM_HEADER
));
180 if (RomHeader
== NULL
) {
181 return EFI_OUT_OF_RESOURCES
;
184 RomPcir
= AllocatePool (sizeof (PCI_DATA_STRUCTURE
));
185 if (RomPcir
== NULL
) {
186 gBS
->FreePool (RomHeader
);
187 return EFI_OUT_OF_RESOURCES
;
190 RomBar
= (UINT32
) RomBase
;
195 RomDecode (PciDevice
, RomBarIndex
, RomBar
, TRUE
);
197 RomBarOffset
= RomBar
;
198 retStatus
= EFI_NOT_FOUND
;
202 PciDevice
->PciRootBridgeIo
->Mem
.Read (
203 PciDevice
->PciRootBridgeIo
,
206 sizeof (PCI_EXPANSION_ROM_HEADER
),
210 if (RomHeader
->Signature
!= PCI_EXPANSION_ROM_HEADER_SIGNATURE
) {
211 RomBarOffset
= RomBarOffset
+ 512;
215 RomImageSize
= RomImageSize
+ 512;
221 OffsetPcir
= RomHeader
->PcirOffset
;
222 PciDevice
->PciRootBridgeIo
->Mem
.Read (
223 PciDevice
->PciRootBridgeIo
,
225 RomBarOffset
+ OffsetPcir
,
226 sizeof (PCI_DATA_STRUCTURE
),
229 if (RomPcir
->CodeType
== PCI_CODE_TYPE_PCAT_IMAGE
) {
230 CodeType
= PCI_CODE_TYPE_PCAT_IMAGE
;
232 Indicator
= RomPcir
->Indicator
;
233 RomImageSize
= RomImageSize
+ RomPcir
->ImageLength
* 512;
234 RomBarOffset
= RomBarOffset
+ RomPcir
->ImageLength
* 512;
235 } while (((Indicator
& 0x80) == 0x00) && ((RomBarOffset
- RomBar
) < RomSize
));
238 // Some Legacy Cards do not report the correct ImageLength so used the maximum
239 // of the legacy length and the PCIR Image Length
241 if (CodeType
== PCI_CODE_TYPE_PCAT_IMAGE
) {
242 RomImageSize
= MAX(RomImageSize
, (((EFI_LEGACY_EXPANSION_ROM_HEADER
*)RomHeader
)->Size512
* 512));
245 if (RomImageSize
> 0) {
246 retStatus
= EFI_SUCCESS
;
247 Image
= AllocatePool ((UINT32
) RomImageSize
);
249 RomDecode (PciDevice
, RomBarIndex
, RomBar
, FALSE
);
250 gBS
->FreePool (RomHeader
);
251 gBS
->FreePool (RomPcir
);
252 return EFI_OUT_OF_RESOURCES
;
256 // Copy Rom image into memory
258 PciDevice
->PciRootBridgeIo
->Mem
.Read (
259 PciDevice
->PciRootBridgeIo
,
262 (UINT32
) RomImageSize
,
268 RomDecode (PciDevice
, RomBarIndex
, RomBar
, FALSE
);
270 PciDevice
->PciIo
.RomSize
= RomImageSize
;
271 PciDevice
->PciIo
.RomImage
= RomInMemory
;
273 PciRomAddImageMapping (
275 PciDevice
->PciRootBridgeIo
->SegmentNumber
,
276 PciDevice
->BusNumber
,
277 PciDevice
->DeviceNumber
,
278 PciDevice
->FunctionNumber
,
279 (UINT64
) (UINTN
) PciDevice
->PciIo
.RomImage
,
280 PciDevice
->PciIo
.RomSize
284 // Free allocated memory
286 gBS
->FreePool (RomHeader
);
287 gBS
->FreePool (RomPcir
);
294 IN PCI_IO_DEVICE
*PciDevice
,
295 IN UINT8 RomBarIndex
,
308 // TODO: PciDevice - add argument and description to function comment
309 // TODO: RomBarIndex - add argument and description to function comment
310 // TODO: RomBar - add argument and description to function comment
311 // TODO: Enable - add argument and description to function comment
312 // TODO: EFI_SUCCESS - add return value to function comment
316 EFI_PCI_IO_PROTOCOL
*PciIo
;
318 PciIo
= &PciDevice
->PciIo
;
323 for (Offset
= 0x10; Offset
<= 0x24; Offset
+= sizeof (UINT32
)) {
324 PciIoWrite (PciIo
, EfiPciIoWidthUint32
, Offset
, 1, &gAllZero
);
328 // set the Rom base address: now is hardcode
329 // enable its decoder
331 Value32
= RomBar
| 0x1;
334 (EFI_PCI_IO_PROTOCOL_WIDTH
) EfiPciWidthUint32
,
341 // Programe all upstream bridge
343 ProgrameUpstreamBridgeForRom(PciDevice
, RomBar
, TRUE
);
346 // Setting the memory space bit in the function's command register
348 PciEnableCommandRegister(PciDevice
, EFI_PCI_COMMAND_MEMORY_SPACE
);
353 // disable command register decode to memory
355 PciDisableCommandRegister(PciDevice
, EFI_PCI_COMMAND_MEMORY_SPACE
);
358 // Destroy the programmed bar in all the upstream bridge.
360 ProgrameUpstreamBridgeForRom(PciDevice
, RomBar
, FALSE
);
363 // disable rom decode
365 Value32
= 0xFFFFFFFE;
368 (EFI_PCI_IO_PROTOCOL_WIDTH
) EfiPciWidthUint32
,
382 PCI_IO_DEVICE
*PciDevice
388 Process the oprom image.
391 PciDevice A pointer to a pci device.
404 EFI_HANDLE ImageHandle
;
406 EFI_STATUS retStatus
;
409 UINT32 DestinationSize
;
413 VOID
*DecompressedImageBuffer
;
415 EFI_DECOMPRESS_PROTOCOL
*Decompress
;
416 EFI_PCI_EXPANSION_ROM_HEADER
*EfiRomHeader
;
417 PCI_DATA_STRUCTURE
*Pcir
;
422 // Get the Address of the Rom image
424 RomBar
= PciDevice
->PciIo
.RomImage
;
425 RomBarOffset
= (UINT8
*) RomBar
;
426 retStatus
= EFI_NOT_FOUND
;
430 EfiRomHeader
= (EFI_PCI_EXPANSION_ROM_HEADER
*) RomBarOffset
;
431 if (EfiRomHeader
->Signature
!= PCI_EXPANSION_ROM_HEADER_SIGNATURE
) {
432 RomBarOffset
= RomBarOffset
+ 512;
441 Pcir
= (PCI_DATA_STRUCTURE
*) (RomBarOffset
+ EfiRomHeader
->PcirOffset
);
442 ImageSize
= (UINT32
) (Pcir
->ImageLength
* 512);
443 Indicator
= Pcir
->Indicator
;
445 if ((Pcir
->CodeType
== PCI_CODE_TYPE_EFI_IMAGE
) &&
446 (EfiRomHeader
->EfiSignature
== EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE
)) {
448 if ((EfiRomHeader
->EfiSubsystem
== EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
) ||
449 (EfiRomHeader
->EfiSubsystem
== EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
)) {
451 ImageOffset
= EfiRomHeader
->EfiImageHeaderOffset
;
452 ImageSize
= (UINT32
) (EfiRomHeader
->InitializationSize
* 512);
454 ImageBuffer
= (VOID
*) (RomBarOffset
+ ImageOffset
);
455 ImageLength
= ImageSize
- (UINT32
)ImageOffset
;
456 DecompressedImageBuffer
= NULL
;
459 // decompress here if needed
462 if (EfiRomHeader
->CompressionType
> EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED
) {
466 if (EfiRomHeader
->CompressionType
== EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED
) {
467 Status
= gBS
->LocateProtocol (&gEfiDecompressProtocolGuid
, NULL
, (VOID
**) &Decompress
);
468 if (EFI_ERROR (Status
)) {
472 Status
= Decompress
->GetInfo (
479 if (!EFI_ERROR (Status
)) {
480 DecompressedImageBuffer
= NULL
;
481 DecompressedImageBuffer
= AllocatePool (DestinationSize
);
482 if (DecompressedImageBuffer
!= NULL
) {
483 Scratch
= AllocatePool (ScratchSize
);
484 if (Scratch
!= NULL
) {
485 Status
= Decompress
->Decompress (
489 DecompressedImageBuffer
,
494 if (!EFI_ERROR (Status
)) {
495 ImageBuffer
= DecompressedImageBuffer
;
496 ImageLength
= DestinationSize
;
500 gBS
->FreePool (Scratch
);
509 // load image and start image
511 Status
= gBS
->LoadImage (
513 gPciBusDriverBinding
.DriverBindingHandle
,
519 if (!EFI_ERROR (Status
)) {
520 Status
= gBS
->StartImage (ImageHandle
, NULL
, NULL
);
521 if (!EFI_ERROR (Status
)) {
522 AddDriver (PciDevice
, ImageHandle
);
523 PciRomAddImageMapping (
525 PciDevice
->PciRootBridgeIo
->SegmentNumber
,
526 PciDevice
->BusNumber
,
527 PciDevice
->DeviceNumber
,
528 PciDevice
->FunctionNumber
,
529 (UINT64
) (UINTN
) PciDevice
->PciIo
.RomImage
,
530 PciDevice
->PciIo
.RomSize
532 retStatus
= EFI_SUCCESS
;
537 RomBarOffset
= RomBarOffset
+ ImageSize
;
539 RomBarOffset
= RomBarOffset
+ ImageSize
;
542 RomBarOffset
= RomBarOffset
+ ImageSize
;
545 } while (((Indicator
& 0x80) == 0x00) && ((UINTN
) (RomBarOffset
- (UINT8
*) RomBar
) < PciDevice
->RomSize
));