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.
25 #include "PciResourceSupport.h"
29 IN PCI_IO_DEVICE
*PciIoDevice
40 // TODO: PciIoDevice - add argument and description to function comment
41 // TODO: EFI_NOT_FOUND - add return value to function comment
42 // TODO: EFI_SUCCESS - add return value to function comment
51 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
53 Bus
= PciIoDevice
->BusNumber
;
54 Device
= PciIoDevice
->DeviceNumber
;
55 Function
= PciIoDevice
->FunctionNumber
;
57 PciRootBridgeIo
= PciIoDevice
->PciRootBridgeIo
;
60 // offset is 48 if is not ppb
66 RomBarIndex
= PCI_DEVICE_ROMBAR
;
68 if (IS_PCI_BRIDGE (&PciIoDevice
->Pci
)) {
76 RomBarIndex
= PCI_BRIDGE_ROMBAR
;
79 // the bit0 is 0 to prevent the enabling of the Rom address decoder
82 Address
= EFI_PCI_ADDRESS (Bus
, Device
, Function
, RomBarIndex
);
84 Status
= PciRootBridgeIo
->Pci
.Write (
91 if (EFI_ERROR (Status
)) {
98 Status
= PciRootBridgeIo
->Pci
.Read (
105 if (EFI_ERROR (Status
)) {
109 AllOnes
&= 0xFFFFFFFC;
110 if ((AllOnes
== 0) || (AllOnes
== 0xFFFFFFFC)) {
111 return EFI_NOT_FOUND
;
114 PciIoDevice
->RomSize
= (UINT64
) ((~AllOnes
) + 1);
121 IN PCI_IO_DEVICE
*PciDevice
,
128 Load option rom image for specified PCI device
135 // TODO: PciDevice - add argument and description to function comment
136 // TODO: RomBase - add argument and description to function comment
137 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
138 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
139 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
147 EFI_STATUS retStatus
;
150 PCI_EXPANSION_ROM_HEADER
*RomHeader
;
151 PCI_DATA_STRUCTURE
*RomPcir
;
156 RomSize
= PciDevice
->RomSize
;
164 // Get the RomBarIndex
170 RomBarIndex
= PCI_DEVICE_ROMBAR
;
171 if (IS_PCI_BRIDGE (&(PciDevice
->Pci
))) {
179 RomBarIndex
= PCI_BRIDGE_ROMBAR
;
182 // Allocate memory for Rom header and PCIR
184 RomHeader
= AllocatePool (sizeof (PCI_EXPANSION_ROM_HEADER
));
185 if (RomHeader
== NULL
) {
186 return EFI_OUT_OF_RESOURCES
;
189 RomPcir
= AllocatePool (sizeof (PCI_DATA_STRUCTURE
));
190 if (RomPcir
== NULL
) {
191 gBS
->FreePool (RomHeader
);
192 return EFI_OUT_OF_RESOURCES
;
195 RomBar
= (UINT32
) RomBase
;
200 RomDecode (PciDevice
, RomBarIndex
, RomBar
, TRUE
);
202 RomBarOffset
= RomBar
;
203 retStatus
= EFI_NOT_FOUND
;
207 PciDevice
->PciRootBridgeIo
->Mem
.Read (
208 PciDevice
->PciRootBridgeIo
,
211 sizeof (PCI_EXPANSION_ROM_HEADER
),
215 if (RomHeader
->Signature
!= PCI_EXPANSION_ROM_HEADER_SIGNATURE
) {
216 RomBarOffset
= RomBarOffset
+ 512;
220 RomImageSize
= RomImageSize
+ 512;
226 OffsetPcir
= RomHeader
->PcirOffset
;
227 PciDevice
->PciRootBridgeIo
->Mem
.Read (
228 PciDevice
->PciRootBridgeIo
,
230 RomBarOffset
+ OffsetPcir
,
231 sizeof (PCI_DATA_STRUCTURE
),
234 Indicator
= RomPcir
->Indicator
;
235 RomImageSize
= RomImageSize
+ RomPcir
->ImageLength
* 512;
236 RomBarOffset
= RomBarOffset
+ RomPcir
->ImageLength
* 512;
237 } while (((Indicator
& 0x80) == 0x00) && ((RomBarOffset
- RomBar
) < RomSize
));
239 if (RomImageSize
> 0) {
240 retStatus
= EFI_SUCCESS
;
241 Image
= AllocatePool ((UINT32
) RomImageSize
);
243 RomDecode (PciDevice
, RomBarIndex
, RomBar
, FALSE
);
244 gBS
->FreePool (RomHeader
);
245 gBS
->FreePool (RomPcir
);
246 return EFI_OUT_OF_RESOURCES
;
250 // Copy Rom image into memory
252 PciDevice
->PciRootBridgeIo
->Mem
.Read (
253 PciDevice
->PciRootBridgeIo
,
256 (UINT32
) RomImageSize
,
262 RomDecode (PciDevice
, RomBarIndex
, RomBar
, FALSE
);
264 PciDevice
->PciIo
.RomSize
= RomImageSize
;
265 PciDevice
->PciIo
.RomImage
= RomInMemory
;
267 PciRomAddImageMapping (
269 PciDevice
->PciRootBridgeIo
->SegmentNumber
,
270 PciDevice
->BusNumber
,
271 PciDevice
->DeviceNumber
,
272 PciDevice
->FunctionNumber
,
273 (UINT64
) (UINTN
) PciDevice
->PciIo
.RomImage
,
274 PciDevice
->PciIo
.RomSize
278 // Free allocated memory
280 gBS
->FreePool (RomHeader
);
281 gBS
->FreePool (RomPcir
);
288 IN PCI_IO_DEVICE
*PciDevice
,
289 IN UINT8 RomBarIndex
,
302 // TODO: PciDevice - add argument and description to function comment
303 // TODO: RomBarIndex - add argument and description to function comment
304 // TODO: RomBar - add argument and description to function comment
305 // TODO: Enable - add argument and description to function comment
306 // TODO: EFI_SUCCESS - add return value to function comment
310 EFI_PCI_IO_PROTOCOL
*PciIo
;
312 PciIo
= &PciDevice
->PciIo
;
317 for (Offset
= 0x10; Offset
<= 0x24; Offset
+= sizeof (UINT32
)) {
318 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, Offset
, 1, &gAllZero
);
322 // set the Rom base address: now is hardcode
323 // enable its decoder
325 Value32
= RomBar
| 0x1;
328 (EFI_PCI_IO_PROTOCOL_WIDTH
) EfiPciWidthUint32
,
335 // Programe all upstream bridge
337 ProgrameUpstreamBridgeForRom(PciDevice
, RomBar
, TRUE
);
340 // Setting the memory space bit in the function's command register
342 PciEnableCommandRegister(PciDevice
, EFI_PCI_COMMAND_MEMORY_SPACE
);
347 // disable command register decode to memory
349 PciDisableCommandRegister(PciDevice
, EFI_PCI_COMMAND_MEMORY_SPACE
);
352 // Destroy the programmed bar in all the upstream bridge.
354 ProgrameUpstreamBridgeForRom(PciDevice
, RomBar
, FALSE
);
357 // disable rom decode
359 Value32
= 0xFFFFFFFE;
362 (EFI_PCI_IO_PROTOCOL_WIDTH
) EfiPciWidthUint32
,
376 PCI_IO_DEVICE
*PciDevice
382 Process the oprom image.
385 PciDevice A pointer to a pci device.
398 EFI_HANDLE ImageHandle
;
400 EFI_STATUS retStatus
;
403 UINT32 DestinationSize
;
407 VOID
*DecompressedImageBuffer
;
409 EFI_DECOMPRESS_PROTOCOL
*Decompress
;
410 EFI_PCI_EXPANSION_ROM_HEADER
*EfiRomHeader
;
411 PCI_DATA_STRUCTURE
*Pcir
;
416 // Get the Address of the Rom image
418 RomBar
= PciDevice
->PciIo
.RomImage
;
419 RomBarOffset
= (UINT8
*) RomBar
;
420 retStatus
= EFI_NOT_FOUND
;
424 EfiRomHeader
= (EFI_PCI_EXPANSION_ROM_HEADER
*) RomBarOffset
;
425 if (EfiRomHeader
->Signature
!= PCI_EXPANSION_ROM_HEADER_SIGNATURE
) {
426 RomBarOffset
= RomBarOffset
+ 512;
435 Pcir
= (PCI_DATA_STRUCTURE
*) (RomBarOffset
+ EfiRomHeader
->PcirOffset
);
436 ImageSize
= (UINT32
) (Pcir
->ImageLength
* 512);
437 Indicator
= Pcir
->Indicator
;
439 if ((Pcir
->CodeType
== PCI_CODE_TYPE_EFI_IMAGE
) &&
440 (EfiRomHeader
->EfiSignature
== EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE
)) {
442 if ((EfiRomHeader
->EfiSubsystem
== EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
) ||
443 (EfiRomHeader
->EfiSubsystem
== EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
)) {
445 ImageOffset
= EfiRomHeader
->EfiImageHeaderOffset
;
446 ImageSize
= (UINT32
) (EfiRomHeader
->InitializationSize
* 512);
448 ImageBuffer
= (VOID
*) (RomBarOffset
+ ImageOffset
);
449 ImageLength
= ImageSize
- (UINT32
)ImageOffset
;
450 DecompressedImageBuffer
= NULL
;
453 // decompress here if needed
456 if (EfiRomHeader
->CompressionType
> EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED
) {
460 if (EfiRomHeader
->CompressionType
== EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED
) {
461 Status
= gBS
->LocateProtocol (&gEfiDecompressProtocolGuid
, NULL
, (VOID
**) &Decompress
);
462 if (EFI_ERROR (Status
)) {
466 Status
= Decompress
->GetInfo (
473 if (!EFI_ERROR (Status
)) {
474 DecompressedImageBuffer
= NULL
;
475 DecompressedImageBuffer
= AllocatePool (DestinationSize
);
476 if (DecompressedImageBuffer
!= NULL
) {
477 Scratch
= AllocatePool (ScratchSize
);
478 if (Scratch
!= NULL
) {
479 Status
= Decompress
->Decompress (
483 DecompressedImageBuffer
,
488 if (!EFI_ERROR (Status
)) {
489 ImageBuffer
= DecompressedImageBuffer
;
490 ImageLength
= DestinationSize
;
494 gBS
->FreePool (Scratch
);
503 // load image and start image
505 Status
= gBS
->LoadImage (
507 gPciBusDriverBinding
.DriverBindingHandle
,
513 if (!EFI_ERROR (Status
)) {
514 Status
= gBS
->StartImage (ImageHandle
, NULL
, NULL
);
515 if (!EFI_ERROR (Status
)) {
516 AddDriver (PciDevice
, ImageHandle
);
517 PciRomAddImageMapping (
519 PciDevice
->PciRootBridgeIo
->SegmentNumber
,
520 PciDevice
->BusNumber
,
521 PciDevice
->DeviceNumber
,
522 PciDevice
->FunctionNumber
,
523 (UINT64
) (UINTN
) PciDevice
->PciIo
.RomImage
,
524 PciDevice
->PciIo
.RomSize
526 retStatus
= EFI_SUCCESS
;
531 RomBarOffset
= RomBarOffset
+ ImageSize
;
533 RomBarOffset
= RomBarOffset
+ ImageSize
;
536 RomBarOffset
= RomBarOffset
+ ImageSize
;
539 } while (((Indicator
& 0x80) == 0x00) && ((UINTN
) (RomBarOffset
- (UINT8
*) RomBar
) < PciDevice
->RomSize
));