+++ /dev/null
-/*++\r
-\r
-Copyright (c) 2005 - 2012, Intel Corporation. All rights reserved.<BR>\r
-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
-\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
-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
-{\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_EXPANSION_ROM_BASE;\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 = PciRootBridgeIo->Pci.Write (\r
- PciRootBridgeIo,\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 = PciRootBridgeIo->Pci.Read (\r
- PciRootBridgeIo,\r
- EfiPciWidthUint32,\r
- Address,\r
- 1,\r
- &AllOnes\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\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
- DEBUG ((EFI_D_ERROR, "PCIBUS: GetOpRomInfo: OPROM detected!\n"));\r
- DEBUG ((EFI_D_ERROR, "PCIBUS: GetOpRomInfo: B-%x, D-%x, F-%x\n", (UINTN)Bus, (UINTN)Device, (UINTN)Function));\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 ReservedMemoryBase\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
-{\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
- UINT32 LegacyImageLength;\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_EXPANSION_ROM_BASE;\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)ReservedMemoryBase; \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
- LegacyImageLength = 0;\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
- //\r
- // If the pointer to the PCI Data Structure is invalid, no further images can be located. \r
- // The PCI Data Structure must be DWORD aligned. \r
- //\r
- if (OffsetPcir == 0 ||\r
- (OffsetPcir & 3) != 0 ||\r
- RomImageSize + OffsetPcir + sizeof (PCI_DATA_STRUCTURE) > RomSize) {\r
- break;\r
- }\r
- PciDevice->PciRootBridgeIo->Mem.Read (\r
- PciDevice->PciRootBridgeIo,\r
- EfiPciWidthUint8,\r
- RomBarOffset + OffsetPcir,\r
- sizeof (PCI_DATA_STRUCTURE),\r
- (UINT8 *) RomPcir\r
- );\r
- //\r
- // If a valid signature is not present in the PCI Data Structure, no further images can be located.\r
- //\r
- if (RomPcir->Signature != PCI_DATA_STRUCTURE_SIGNATURE) {\r
- break;\r
- }\r
- if (RomImageSize + RomPcir->ImageLength * 512 > RomSize) {\r
- break;\r
- }\r
- if (RomPcir->CodeType == PCI_CODE_TYPE_PCAT_IMAGE) {\r
- CodeType = PCI_CODE_TYPE_PCAT_IMAGE;\r
- LegacyImageLength = ((UINT32)((EFI_LEGACY_EXPANSION_ROM_HEADER *)RomHeader)->Size512) * 512;\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 = MAX (RomImageSize, LegacyImageLength);\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
- //\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
-{\r
- UINT16 CommandValue;\r
- UINT32 Value32;\r
- UINT64 Address;\r
- //EFI_STATUS Status;\r
- EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
- \r
- PciRootBridgeIo = PciDevice->PciRootBridgeIo;\r
- if (Enable) {\r
- Address = EFI_PCI_ADDRESS (PciDevice->BusNumber, PciDevice->DeviceNumber, PciDevice->FunctionNumber, RomBarIndex);\r
- //\r
- // set the Rom base address: now is hardcode\r
- //\r
- PciRootBridgeIo->Pci.Write(\r
- PciRootBridgeIo, \r
- EfiPciWidthUint32, \r
- Address, \r
- 1, \r
- &RomBar);\r
- \r
- //\r
- // enable its decoder\r
- //\r
- Value32 = RomBar | 0x1;\r
- PciRootBridgeIo->Pci.Write(\r
- PciRootBridgeIo, \r
- EfiPciWidthUint32, \r
- Address, \r
- 1, \r
- &Value32);\r
- \r
- //\r
- //setting the memory space bit in the function's command register\r
- //\r
- Address = EFI_PCI_ADDRESS (PciDevice->BusNumber, PciDevice->DeviceNumber, PciDevice->FunctionNumber, 0x04);\r
- PciRootBridgeIo->Pci.Read(\r
- PciRootBridgeIo, \r
- EfiPciWidthUint16, \r
- Address, \r
- 1, \r
- &CommandValue);\r
- \r
- CommandValue = (UINT16)(CommandValue | 0x0002); //0x0003\r
- PciRootBridgeIo->Pci.Write(\r
- PciRootBridgeIo, \r
- EfiPciWidthUint16, \r
- Address, \r
- 1, \r
- &CommandValue);\r
- } else {\r
- //\r
- // disable rom decode\r
- // \r
- Address = EFI_PCI_ADDRESS (PciDevice->BusNumber, PciDevice->DeviceNumber, PciDevice->FunctionNumber, RomBarIndex);\r
- Value32 = 0xfffffffe;\r
- PciRootBridgeIo->Pci.Write(\r
- PciRootBridgeIo, \r
- EfiPciWidthUint32, \r
- Address, \r
- 1, \r
- &Value32);\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 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
- UINT32 InitializationSize;\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
-\r
- if (RomBarOffset == NULL) {\r
- return retStatus;\r
- }\r
- ASSERT (((EFI_PCI_EXPANSION_ROM_HEADER *) RomBarOffset)->Signature == PCI_EXPANSION_ROM_HEADER_SIGNATURE);\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
- continue;\r
- }\r
-\r
- Pcir = (PCI_DATA_STRUCTURE *) (RomBarOffset + EfiRomHeader->PcirOffset);\r
- ASSERT (Pcir->Signature == PCI_DATA_STRUCTURE_SIGNATURE);\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
- ((EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER) ||\r
- (EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER))) {\r
-\r
- ImageOffset = EfiRomHeader->EfiImageHeaderOffset;\r
- InitializationSize = EfiRomHeader->InitializationSize * 512;\r
-\r
- if (InitializationSize <= ImageSize && ImageOffset < InitializationSize) {\r
-\r
- ImageBuffer = (VOID *) (RomBarOffset + ImageOffset);\r
- ImageLength = InitializationSize - (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
- NULL,\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
- 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