+++ /dev/null
-/*++\r
-\r
-Copyright (c) 2006 - 2007, Intel Corporation\r
-All rights reserved. This program and the accompanying materials\r
-are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution. The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-\r
-Module Name:\r
-\r
- PciOptionRomSupport.c\r
-\r
-Abstract:\r
-\r
- PCI Bus Driver\r
-\r
-Revision History\r
-\r
---*/\r
-\r
-#include "pcibus.h"\r
-#include "PciResourceSupport.h"\r
-\r
-#include <IndustryStandard/Pci23.h>\r
-//\r
-// Min Max\r
-//\r
-#define EFI_MIN(a, b) (((a) < (b)) ? (a) : (b))\r
-#define EFI_MAX(a, b) (((a) > (b)) ? (a) : (b))\r
-\r
-\r
-EFI_STATUS\r
-GetOpRomInfo (\r
- IN PCI_IO_DEVICE *PciIoDevice\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
-Arguments:\r
-\r
-Returns:\r
-\r
---*/\r
-// TODO: PciIoDevice - add argument and description to function comment\r
-// TODO: EFI_NOT_FOUND - add return value to function comment\r
-// TODO: EFI_SUCCESS - add return value to function comment\r
-{\r
- UINT8 RomBarIndex;\r
- UINT32 AllOnes;\r
- UINT64 Address;\r
- EFI_STATUS Status;\r
- UINT8 Bus;\r
- UINT8 Device;\r
- UINT8 Function;\r
- EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
-\r
- Bus = PciIoDevice->BusNumber;\r
- Device = PciIoDevice->DeviceNumber;\r
- Function = PciIoDevice->FunctionNumber;\r
-\r
- PciRootBridgeIo = PciIoDevice->PciRootBridgeIo;\r
-\r
- //\r
- // offset is 0x30 if is not ppb\r
- //\r
-\r
- //\r
- // 0x30\r
- //\r
- RomBarIndex = PCI_DEVICE_ROMBAR;\r
-\r
- if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {\r
- //\r
- // if is ppb\r
- //\r
-\r
- //\r
- // 0x38\r
- //\r
- RomBarIndex = PCI_BRIDGE_ROMBAR;\r
- }\r
- //\r
- // the bit0 is 0 to prevent the enabling of the Rom address decoder\r
- //\r
- AllOnes = 0xfffffffe;\r
- Address = EFI_PCI_ADDRESS (Bus, Device, Function, RomBarIndex);\r
-\r
- Status = PciRootBridgeIoWrite (\r
- PciRootBridgeIo,\r
- &PciIoDevice->Pci,\r
- EfiPciWidthUint32,\r
- Address,\r
- 1,\r
- &AllOnes\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- //\r
- // read back\r
- //\r
- Status = PciRootBridgeIoRead (\r
- PciRootBridgeIo,\r
- &PciIoDevice->Pci,\r
- EfiPciWidthUint32,\r
- Address,\r
- 1,\r
- &AllOnes\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
- //\r
- // Bits [1, 10] are reserved\r
- //\r
- AllOnes &= 0xFFFFF800;\r
- if ((AllOnes == 0) || (AllOnes == 0xFFFFF800)) {\r
- return EFI_NOT_FOUND;\r
- }\r
-\r
- PciIoDevice->RomSize = (UINT64) ((~AllOnes) + 1);\r
- return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-LoadOpRomImage (\r
- IN PCI_IO_DEVICE *PciDevice,\r
- IN UINT64 RomBase\r
- )\r
-/*++\r
-\r
-Routine Description:\r
- \r
- Load option rom image for specified PCI device\r
-\r
-Arguments:\r
-\r
-Returns:\r
-\r
---*/\r
-// TODO: PciDevice - add argument and description to function comment\r
-// TODO: RomBase - add argument and description to function comment\r
-// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment\r
-// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment\r
-// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment\r
-{\r
- UINT8 RomBarIndex;\r
- UINT8 Indicator;\r
- UINT16 OffsetPcir;\r
- UINT32 RomBarOffset;\r
- UINT32 RomBar;\r
- EFI_STATUS retStatus;\r
- BOOLEAN FirstCheck;\r
- UINT8 *Image;\r
- PCI_EXPANSION_ROM_HEADER *RomHeader;\r
- PCI_DATA_STRUCTURE *RomPcir;\r
- UINT64 RomSize;\r
- UINT64 RomImageSize;\r
- UINT8 *RomInMemory;\r
- UINT8 CodeType;\r
-\r
- RomSize = PciDevice->RomSize;\r
-\r
- Indicator = 0;\r
- RomImageSize = 0;\r
- RomInMemory = NULL;\r
- CodeType = 0xFF;\r
-\r
- //\r
- // Get the RomBarIndex\r
- //\r
-\r
- //\r
- // 0x30\r
- //\r
- RomBarIndex = PCI_DEVICE_ROMBAR;\r
- if (IS_PCI_BRIDGE (&(PciDevice->Pci))) {\r
- //\r
- // if is ppb\r
- //\r
-\r
- //\r
- // 0x38\r
- //\r
- RomBarIndex = PCI_BRIDGE_ROMBAR;\r
- }\r
- //\r
- // Allocate memory for Rom header and PCIR\r
- //\r
- RomHeader = AllocatePool (sizeof (PCI_EXPANSION_ROM_HEADER));\r
- if (RomHeader == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- RomPcir = AllocatePool (sizeof (PCI_DATA_STRUCTURE));\r
- if (RomPcir == NULL) {\r
- gBS->FreePool (RomHeader);\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- RomBar = (UINT32) RomBase;\r
-\r
- //\r
- // Enable RomBar\r
- //\r
- RomDecode (PciDevice, RomBarIndex, RomBar, TRUE);\r
-\r
- RomBarOffset = RomBar;\r
- retStatus = EFI_NOT_FOUND;\r
- FirstCheck = TRUE;\r
-\r
- do {\r
- PciDevice->PciRootBridgeIo->Mem.Read (\r
- PciDevice->PciRootBridgeIo,\r
- EfiPciWidthUint8,\r
- RomBarOffset,\r
- sizeof (PCI_EXPANSION_ROM_HEADER),\r
- (UINT8 *) RomHeader\r
- );\r
-\r
- if (RomHeader->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) {\r
- RomBarOffset = RomBarOffset + 512;\r
- if (FirstCheck) {\r
- break;\r
- } else {\r
- RomImageSize = RomImageSize + 512;\r
- continue;\r
- }\r
- }\r
-\r
- FirstCheck = FALSE;\r
- OffsetPcir = RomHeader->PcirOffset;\r
- PciDevice->PciRootBridgeIo->Mem.Read (\r
- PciDevice->PciRootBridgeIo,\r
- EfiPciWidthUint8,\r
- RomBarOffset + OffsetPcir,\r
- sizeof (PCI_DATA_STRUCTURE),\r
- (UINT8 *) RomPcir\r
- );\r
- if (RomPcir->CodeType == PCI_CODE_TYPE_PCAT_IMAGE) {\r
- CodeType = PCI_CODE_TYPE_PCAT_IMAGE;\r
- }\r
- Indicator = RomPcir->Indicator;\r
- RomImageSize = RomImageSize + RomPcir->ImageLength * 512;\r
- RomBarOffset = RomBarOffset + RomPcir->ImageLength * 512;\r
- } while (((Indicator & 0x80) == 0x00) && ((RomBarOffset - RomBar) < RomSize));\r
-\r
- //\r
- // Some Legacy Cards do not report the correct ImageLength so used the maximum\r
- // of the legacy length and the PCIR Image Length\r
- //\r
- if (CodeType == PCI_CODE_TYPE_PCAT_IMAGE) {\r
- RomImageSize = EFI_MAX(RomImageSize, (((EFI_LEGACY_EXPANSION_ROM_HEADER *)RomHeader)->Size512 * 512));\r
- }\r
-\r
- if (RomImageSize > 0) {\r
- retStatus = EFI_SUCCESS;\r
- Image = AllocatePool ((UINT32) RomImageSize);\r
- if (Image == NULL) {\r
- RomDecode (PciDevice, RomBarIndex, RomBar, FALSE);\r
- gBS->FreePool (RomHeader);\r
- gBS->FreePool (RomPcir);\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
- \r
- //\r
- // Copy Rom image into memory\r
- //\r
- PciDevice->PciRootBridgeIo->Mem.Read (\r
- PciDevice->PciRootBridgeIo,\r
- EfiPciWidthUint8,\r
- RomBar,\r
- (UINT32) RomImageSize,\r
- Image\r
- );\r
- RomInMemory = Image;\r
- }\r
-\r
- RomDecode (PciDevice, RomBarIndex, RomBar, FALSE);\r
-\r
- PciDevice->PciIo.RomSize = RomImageSize;\r
- PciDevice->PciIo.RomImage = RomInMemory;\r
-\r
- PciRomAddImageMapping (\r
- NULL,\r
- PciDevice->PciRootBridgeIo->SegmentNumber,\r
- PciDevice->BusNumber,\r
- PciDevice->DeviceNumber,\r
- PciDevice->FunctionNumber,\r
- (UINT64) (UINTN) PciDevice->PciIo.RomImage,\r
- PciDevice->PciIo.RomSize\r
- );\r
-\r
- //\r
- // Free allocated memory\r
- //\r
- gBS->FreePool (RomHeader);\r
- gBS->FreePool (RomPcir);\r
-\r
- return retStatus;\r
-}\r
-\r
-EFI_STATUS\r
-RomDecode (\r
- IN PCI_IO_DEVICE *PciDevice,\r
- IN UINT8 RomBarIndex,\r
- IN UINT32 RomBar,\r
- IN BOOLEAN Enable\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
-Arguments:\r
-\r
-Returns:\r
-\r
---*/\r
-// TODO: PciDevice - add argument and description to function comment\r
-// TODO: RomBarIndex - add argument and description to function comment\r
-// TODO: RomBar - add argument and description to function comment\r
-// TODO: Enable - add argument and description to function comment\r
-// TODO: EFI_SUCCESS - add return value to function comment\r
-{\r
- UINT32 Value32;\r
- UINT32 Offset;\r
- EFI_PCI_IO_PROTOCOL *PciIo;\r
-\r
- PciIo = &PciDevice->PciIo;\r
- if (Enable) {\r
- //\r
- // Clear all bars\r
- //\r
- for (Offset = 0x10; Offset <= 0x24; Offset += sizeof (UINT32)) {\r
- PciIoWrite (PciIo, EfiPciIoWidthUint32, Offset, 1, &gAllZero);\r
- }\r
- \r
- //\r
- // set the Rom base address: now is hardcode\r
- // enable its decoder\r
- //\r
- Value32 = RomBar | 0x1;\r
- PciIoWrite (\r
- PciIo,\r
- (EFI_PCI_IO_PROTOCOL_WIDTH) EfiPciWidthUint32,\r
- RomBarIndex,\r
- 1,\r
- &Value32\r
- );\r
-\r
- //\r
- // Programe all upstream bridge\r
- //\r
- ProgrameUpstreamBridgeForRom(PciDevice, RomBar, TRUE);\r
-\r
- //\r
- // Setting the memory space bit in the function's command register\r
- //\r
- PciEnableCommandRegister(PciDevice, EFI_PCI_COMMAND_MEMORY_SPACE);\r
-\r
- } else {\r
- \r
- //\r
- // disable command register decode to memory\r
- //\r
- PciDisableCommandRegister(PciDevice, EFI_PCI_COMMAND_MEMORY_SPACE);\r
-\r
- //\r
- // Destroy the programmed bar in all the upstream bridge.\r
- //\r
- ProgrameUpstreamBridgeForRom(PciDevice, RomBar, FALSE);\r
-\r
- //\r
- // disable rom decode\r
- //\r
- Value32 = 0xFFFFFFFE;\r
- PciIoWrite (\r
- PciIo,\r
- (EFI_PCI_IO_PROTOCOL_WIDTH) EfiPciWidthUint32,\r
- RomBarIndex,\r
- 1,\r
- &Value32\r
- );\r
-\r
- }\r
-\r
- return EFI_SUCCESS;\r
-\r
-}\r
-\r
-EFI_STATUS\r
-ProcessOpRomImage (\r
- PCI_IO_DEVICE *PciDevice\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Process the oprom image.\r
- \r
-Arguments:\r
- PciDevice A pointer to a pci device.\r
-\r
-Returns:\r
-\r
- EFI Status.\r
- \r
---*/\r
-{\r
- UINT8 Indicator;\r
- UINT32 ImageSize;\r
- UINT16 ImageOffset;\r
- VOID *RomBar;\r
- UINT8 *RomBarOffset;\r
- EFI_HANDLE ImageHandle;\r
- EFI_STATUS Status;\r
- EFI_STATUS retStatus;\r
- BOOLEAN FirstCheck;\r
- BOOLEAN SkipImage;\r
- UINT32 DestinationSize;\r
- UINT32 ScratchSize;\r
- UINT8 *Scratch;\r
- VOID *ImageBuffer;\r
- VOID *DecompressedImageBuffer;\r
- UINT32 ImageLength;\r
- EFI_DECOMPRESS_PROTOCOL *Decompress;\r
- EFI_PCI_EXPANSION_ROM_HEADER *EfiRomHeader;\r
- PCI_DATA_STRUCTURE *Pcir;\r
-\r
- Indicator = 0;\r
-\r
- //\r
- // Get the Address of the Rom image\r
- //\r
- RomBar = PciDevice->PciIo.RomImage;\r
- RomBarOffset = (UINT8 *) RomBar;\r
- retStatus = EFI_NOT_FOUND;\r
- FirstCheck = TRUE;\r
-\r
- do {\r
- EfiRomHeader = (EFI_PCI_EXPANSION_ROM_HEADER *) RomBarOffset;\r
- if (EfiRomHeader->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) {\r
- RomBarOffset = RomBarOffset + 512;\r
- if (FirstCheck) {\r
- break;\r
- } else {\r
- continue;\r
- }\r
- }\r
-\r
- FirstCheck = FALSE;\r
- Pcir = (PCI_DATA_STRUCTURE *) (RomBarOffset + EfiRomHeader->PcirOffset);\r
- ImageSize = (UINT32) (Pcir->ImageLength * 512);\r
- Indicator = Pcir->Indicator;\r
-\r
- if ((Pcir->CodeType == PCI_CODE_TYPE_EFI_IMAGE) && \r
- (EfiRomHeader->EfiSignature == EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE)) {\r
-\r
- if ((EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER) ||\r
- (EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER)) {\r
-\r
- ImageOffset = EfiRomHeader->EfiImageHeaderOffset;\r
- ImageSize = (UINT32) (EfiRomHeader->InitializationSize * 512);\r
-\r
- ImageBuffer = (VOID *) (RomBarOffset + ImageOffset);\r
- ImageLength = ImageSize - (UINT32)ImageOffset;\r
- DecompressedImageBuffer = NULL;\r
-\r
- //\r
- // decompress here if needed\r
- //\r
- SkipImage = FALSE;\r
- if (EfiRomHeader->CompressionType > EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) {\r
- SkipImage = TRUE;\r
- }\r
-\r
- if (EfiRomHeader->CompressionType == EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) {\r
- Status = gBS->LocateProtocol (&gEfiDecompressProtocolGuid, NULL, (VOID **) &Decompress);\r
- if (EFI_ERROR (Status)) {\r
- SkipImage = TRUE;\r
- } else {\r
- SkipImage = TRUE;\r
- Status = Decompress->GetInfo (\r
- Decompress,\r
- ImageBuffer,\r
- ImageLength,\r
- &DestinationSize,\r
- &ScratchSize\r
- );\r
- if (!EFI_ERROR (Status)) {\r
- DecompressedImageBuffer = NULL;\r
- DecompressedImageBuffer = AllocatePool (DestinationSize);\r
- if (DecompressedImageBuffer != NULL) {\r
- Scratch = AllocatePool (ScratchSize);\r
- if (Scratch != NULL) {\r
- Status = Decompress->Decompress (\r
- Decompress,\r
- ImageBuffer,\r
- ImageLength,\r
- DecompressedImageBuffer,\r
- DestinationSize,\r
- Scratch,\r
- ScratchSize\r
- );\r
- if (!EFI_ERROR (Status)) {\r
- ImageBuffer = DecompressedImageBuffer;\r
- ImageLength = DestinationSize;\r
- SkipImage = FALSE;\r
- }\r
-\r
- gBS->FreePool (Scratch);\r
- }\r
- }\r
- }\r
- }\r
- }\r
-\r
- if (!SkipImage) {\r
- //\r
- // load image and start image\r
- //\r
- Status = gBS->LoadImage (\r
- FALSE,\r
- gPciBusDriverBinding.DriverBindingHandle,\r
- PciDevice->Handle,\r
- ImageBuffer,\r
- ImageLength,\r
- &ImageHandle\r
- );\r
- if (!EFI_ERROR (Status)) {\r
- Status = gBS->StartImage (ImageHandle, NULL, NULL);\r
- if (!EFI_ERROR (Status)) {\r
- AddDriver (PciDevice, ImageHandle);\r
- PciRomAddImageMapping (\r
- ImageHandle,\r
- PciDevice->PciRootBridgeIo->SegmentNumber,\r
- PciDevice->BusNumber,\r
- PciDevice->DeviceNumber,\r
- PciDevice->FunctionNumber,\r
- (UINT64) (UINTN) PciDevice->PciIo.RomImage,\r
- PciDevice->PciIo.RomSize\r
- );\r
- retStatus = EFI_SUCCESS;\r
- }\r
- }\r
- }\r
-\r
- RomBarOffset = RomBarOffset + ImageSize;\r
- } else {\r
- RomBarOffset = RomBarOffset + ImageSize;\r
- }\r
- } else {\r
- RomBarOffset = RomBarOffset + ImageSize;\r
- }\r
-\r
- } while (((Indicator & 0x80) == 0x00) && ((UINTN) (RomBarOffset - (UINT8 *) RomBar) < PciDevice->RomSize));\r
-\r
- return retStatus;\r
-\r
-}\r