3 Copyright (c) 2006 - 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.
25 #include "PciResourceSupport.h"
27 #include <IndustryStandard/Pci23.h>
31 #define EFI_MIN(a, b) (((a) < (b)) ? (a) : (b))
32 #define EFI_MAX(a, b) (((a) > (b)) ? (a) : (b))
37 IN PCI_IO_DEVICE
*PciIoDevice
48 // TODO: PciIoDevice - add argument and description to function comment
49 // TODO: EFI_NOT_FOUND - add return value to function comment
50 // TODO: EFI_SUCCESS - add return value to function comment
59 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
61 Bus
= PciIoDevice
->BusNumber
;
62 Device
= PciIoDevice
->DeviceNumber
;
63 Function
= PciIoDevice
->FunctionNumber
;
65 PciRootBridgeIo
= PciIoDevice
->PciRootBridgeIo
;
68 // offset is 0x30 if is not ppb
74 RomBarIndex
= PCI_DEVICE_ROMBAR
;
76 if (IS_PCI_BRIDGE (&PciIoDevice
->Pci
)) {
84 RomBarIndex
= PCI_BRIDGE_ROMBAR
;
87 // the bit0 is 0 to prevent the enabling of the Rom address decoder
90 Address
= EFI_PCI_ADDRESS (Bus
, Device
, Function
, RomBarIndex
);
92 Status
= PciRootBridgeIoWrite (
100 if (EFI_ERROR (Status
)) {
107 Status
= PciRootBridgeIoRead (
115 if (EFI_ERROR (Status
)) {
119 // Bits [1, 10] are reserved
121 AllOnes
&= 0xFFFFF800;
122 if ((AllOnes
== 0) || (AllOnes
== 0xFFFFF800)) {
123 return EFI_NOT_FOUND
;
126 PciIoDevice
->RomSize
= (UINT64
) ((~AllOnes
) + 1);
132 IN PCI_IO_DEVICE
*PciDevice
,
139 Load option rom image for specified PCI device
146 // TODO: PciDevice - add argument and description to function comment
147 // TODO: RomBase - add argument and description to function comment
148 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
149 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
150 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
157 EFI_STATUS retStatus
;
160 PCI_EXPANSION_ROM_HEADER
*RomHeader
;
161 PCI_DATA_STRUCTURE
*RomPcir
;
167 RomSize
= PciDevice
->RomSize
;
175 // Get the RomBarIndex
181 RomBarIndex
= PCI_DEVICE_ROMBAR
;
182 if (IS_PCI_BRIDGE (&(PciDevice
->Pci
))) {
190 RomBarIndex
= PCI_BRIDGE_ROMBAR
;
193 // Allocate memory for Rom header and PCIR
195 RomHeader
= AllocatePool (sizeof (PCI_EXPANSION_ROM_HEADER
));
196 if (RomHeader
== NULL
) {
197 return EFI_OUT_OF_RESOURCES
;
200 RomPcir
= AllocatePool (sizeof (PCI_DATA_STRUCTURE
));
201 if (RomPcir
== NULL
) {
202 gBS
->FreePool (RomHeader
);
203 return EFI_OUT_OF_RESOURCES
;
206 RomBar
= (UINT32
) RomBase
;
211 RomDecode (PciDevice
, RomBarIndex
, RomBar
, TRUE
);
213 RomBarOffset
= RomBar
;
214 retStatus
= EFI_NOT_FOUND
;
218 PciDevice
->PciRootBridgeIo
->Mem
.Read (
219 PciDevice
->PciRootBridgeIo
,
222 sizeof (PCI_EXPANSION_ROM_HEADER
),
226 if (RomHeader
->Signature
!= PCI_EXPANSION_ROM_HEADER_SIGNATURE
) {
227 RomBarOffset
= RomBarOffset
+ 512;
231 RomImageSize
= RomImageSize
+ 512;
237 OffsetPcir
= RomHeader
->PcirOffset
;
238 PciDevice
->PciRootBridgeIo
->Mem
.Read (
239 PciDevice
->PciRootBridgeIo
,
241 RomBarOffset
+ OffsetPcir
,
242 sizeof (PCI_DATA_STRUCTURE
),
245 if (RomPcir
->CodeType
== PCI_CODE_TYPE_PCAT_IMAGE
) {
246 CodeType
= PCI_CODE_TYPE_PCAT_IMAGE
;
248 Indicator
= RomPcir
->Indicator
;
249 RomImageSize
= RomImageSize
+ RomPcir
->ImageLength
* 512;
250 RomBarOffset
= RomBarOffset
+ RomPcir
->ImageLength
* 512;
251 } while (((Indicator
& 0x80) == 0x00) && ((RomBarOffset
- RomBar
) < RomSize
));
254 // Some Legacy Cards do not report the correct ImageLength so used the maximum
255 // of the legacy length and the PCIR Image Length
257 if (CodeType
== PCI_CODE_TYPE_PCAT_IMAGE
) {
258 RomImageSize
= EFI_MAX(RomImageSize
, (((EFI_LEGACY_EXPANSION_ROM_HEADER
*)RomHeader
)->Size512
* 512));
261 if (RomImageSize
> 0) {
262 retStatus
= EFI_SUCCESS
;
263 Image
= AllocatePool ((UINT32
) RomImageSize
);
265 RomDecode (PciDevice
, RomBarIndex
, RomBar
, FALSE
);
266 gBS
->FreePool (RomHeader
);
267 gBS
->FreePool (RomPcir
);
268 return EFI_OUT_OF_RESOURCES
;
272 // Copy Rom image into memory
274 PciDevice
->PciRootBridgeIo
->Mem
.Read (
275 PciDevice
->PciRootBridgeIo
,
278 (UINT32
) RomImageSize
,
284 RomDecode (PciDevice
, RomBarIndex
, RomBar
, FALSE
);
286 PciDevice
->PciIo
.RomSize
= RomImageSize
;
287 PciDevice
->PciIo
.RomImage
= RomInMemory
;
289 PciRomAddImageMapping (
291 PciDevice
->PciRootBridgeIo
->SegmentNumber
,
292 PciDevice
->BusNumber
,
293 PciDevice
->DeviceNumber
,
294 PciDevice
->FunctionNumber
,
295 (UINT64
) (UINTN
) PciDevice
->PciIo
.RomImage
,
296 PciDevice
->PciIo
.RomSize
300 // Free allocated memory
302 gBS
->FreePool (RomHeader
);
303 gBS
->FreePool (RomPcir
);
310 IN PCI_IO_DEVICE
*PciDevice
,
311 IN UINT8 RomBarIndex
,
324 // TODO: PciDevice - add argument and description to function comment
325 // TODO: RomBarIndex - add argument and description to function comment
326 // TODO: RomBar - add argument and description to function comment
327 // TODO: Enable - add argument and description to function comment
328 // TODO: EFI_SUCCESS - add return value to function comment
332 EFI_PCI_IO_PROTOCOL
*PciIo
;
334 PciIo
= &PciDevice
->PciIo
;
339 for (Offset
= 0x10; Offset
<= 0x24; Offset
+= sizeof (UINT32
)) {
340 PciIoWrite (PciIo
, EfiPciIoWidthUint32
, Offset
, 1, &gAllZero
);
344 // set the Rom base address: now is hardcode
345 // enable its decoder
347 Value32
= RomBar
| 0x1;
350 (EFI_PCI_IO_PROTOCOL_WIDTH
) EfiPciWidthUint32
,
357 // Programe all upstream bridge
359 ProgrameUpstreamBridgeForRom(PciDevice
, RomBar
, TRUE
);
362 // Setting the memory space bit in the function's command register
364 PciEnableCommandRegister(PciDevice
, EFI_PCI_COMMAND_MEMORY_SPACE
);
369 // disable command register decode to memory
371 PciDisableCommandRegister(PciDevice
, EFI_PCI_COMMAND_MEMORY_SPACE
);
374 // Destroy the programmed bar in all the upstream bridge.
376 ProgrameUpstreamBridgeForRom(PciDevice
, RomBar
, FALSE
);
379 // disable rom decode
381 Value32
= 0xFFFFFFFE;
384 (EFI_PCI_IO_PROTOCOL_WIDTH
) EfiPciWidthUint32
,
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
;
425 UINT32 DestinationSize
;
429 VOID
*DecompressedImageBuffer
;
431 EFI_DECOMPRESS_PROTOCOL
*Decompress
;
432 EFI_PCI_EXPANSION_ROM_HEADER
*EfiRomHeader
;
433 PCI_DATA_STRUCTURE
*Pcir
;
438 // Get the Address of the Rom image
440 RomBar
= PciDevice
->PciIo
.RomImage
;
441 RomBarOffset
= (UINT8
*) RomBar
;
442 retStatus
= EFI_NOT_FOUND
;
446 EfiRomHeader
= (EFI_PCI_EXPANSION_ROM_HEADER
*) RomBarOffset
;
447 if (EfiRomHeader
->Signature
!= PCI_EXPANSION_ROM_HEADER_SIGNATURE
) {
448 RomBarOffset
= RomBarOffset
+ 512;
457 Pcir
= (PCI_DATA_STRUCTURE
*) (RomBarOffset
+ EfiRomHeader
->PcirOffset
);
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
)) {
464 if ((EfiRomHeader
->EfiSubsystem
== EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
) ||
465 (EfiRomHeader
->EfiSubsystem
== EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
)) {
467 ImageOffset
= EfiRomHeader
->EfiImageHeaderOffset
;
468 ImageSize
= (UINT32
) (EfiRomHeader
->InitializationSize
* 512);
470 ImageBuffer
= (VOID
*) (RomBarOffset
+ ImageOffset
);
471 ImageLength
= ImageSize
- (UINT32
)ImageOffset
;
472 DecompressedImageBuffer
= NULL
;
475 // decompress here if needed
478 if (EfiRomHeader
->CompressionType
> EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED
) {
482 if (EfiRomHeader
->CompressionType
== EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED
) {
483 Status
= gBS
->LocateProtocol (&gEfiDecompressProtocolGuid
, NULL
, (VOID
**) &Decompress
);
484 if (EFI_ERROR (Status
)) {
488 Status
= Decompress
->GetInfo (
495 if (!EFI_ERROR (Status
)) {
496 DecompressedImageBuffer
= NULL
;
497 DecompressedImageBuffer
= AllocatePool (DestinationSize
);
498 if (DecompressedImageBuffer
!= NULL
) {
499 Scratch
= AllocatePool (ScratchSize
);
500 if (Scratch
!= NULL
) {
501 Status
= Decompress
->Decompress (
505 DecompressedImageBuffer
,
510 if (!EFI_ERROR (Status
)) {
511 ImageBuffer
= DecompressedImageBuffer
;
512 ImageLength
= DestinationSize
;
516 gBS
->FreePool (Scratch
);
525 // load image and start image
527 Status
= gBS
->LoadImage (
529 gPciBusDriverBinding
.DriverBindingHandle
,
535 if (!EFI_ERROR (Status
)) {
536 Status
= gBS
->StartImage (ImageHandle
, NULL
, NULL
);
537 if (!EFI_ERROR (Status
)) {
538 AddDriver (PciDevice
, ImageHandle
);
539 PciRomAddImageMapping (
541 PciDevice
->PciRootBridgeIo
->SegmentNumber
,
542 PciDevice
->BusNumber
,
543 PciDevice
->DeviceNumber
,
544 PciDevice
->FunctionNumber
,
545 (UINT64
) (UINTN
) PciDevice
->PciIo
.RomImage
,
546 PciDevice
->PciIo
.RomSize
548 retStatus
= EFI_SUCCESS
;
553 RomBarOffset
= RomBarOffset
+ ImageSize
;
555 RomBarOffset
= RomBarOffset
+ ImageSize
;
558 RomBarOffset
= RomBarOffset
+ ImageSize
;
561 } while (((Indicator
& 0x80) == 0x00) && ((UINTN
) (RomBarOffset
- (UINT8
*) RomBar
) < PciDevice
->RomSize
));