X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=MdeModulePkg%2FBus%2FPci%2FPciBusDxe%2FPciOptionRomSupport.c;h=c994ed5fe34b8cad0c1aac80230f5cd8df1952c4;hp=19803efb2c6acc29370416fb443ffb682f8c20c9;hb=615a72400bca338aa92579a726c4669b4185dc43;hpb=9060e3ec6dfd6048724832947933650cde873381 diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciOptionRomSupport.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciOptionRomSupport.c index 19803efb2c..c994ed5fe3 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciOptionRomSupport.c +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciOptionRomSupport.c @@ -1,14 +1,8 @@ /** @file PCI Rom supporting funtions implementation for PCI Bus module. -Copyright (c) 2006 - 2009, Intel Corporation -All rights reserved. This program and the accompanying materials -are licensed and made available under the terms and conditions of the BSD License -which accompanies this distribution. The full text of the license may be found at -http://opensource.org/licenses/bsd-license.php - -THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent **/ @@ -53,6 +47,7 @@ LocalLoadFile2 ( UINT32 ScratchSize; VOID *Scratch; EFI_DECOMPRESS_PROTOCOL *Decompress; + UINT32 InitializationSize; EfiOpRomImageNode = (MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH *) FilePath; if ((EfiOpRomImageNode == NULL) || @@ -76,7 +71,7 @@ LocalLoadFile2 ( Pcir = (PCI_DATA_STRUCTURE *) ((UINT8 *) EfiRomHeader + EfiRomHeader->PcirOffset); - + ASSERT (Pcir->Signature == PCI_DATA_STRUCTURE_SIGNATURE); if ((Pcir->CodeType == PCI_CODE_TYPE_EFI_IMAGE) && (EfiRomHeader->EfiSignature == EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE) && @@ -85,9 +80,14 @@ LocalLoadFile2 ( (EfiRomHeader->CompressionType <= EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) ) { - ImageSize = (UINT32) EfiRomHeader->InitializationSize * 512; + ImageSize = Pcir->ImageLength * 512; + InitializationSize = (UINT32) EfiRomHeader->InitializationSize * 512; + if (InitializationSize > ImageSize || EfiRomHeader->EfiImageHeaderOffset >= InitializationSize) { + return EFI_NOT_FOUND; + } + ImageBuffer = (UINT8 *) EfiRomHeader + EfiRomHeader->EfiImageHeaderOffset; - ImageLength = ImageSize - EfiRomHeader->EfiImageHeaderOffset; + ImageLength = InitializationSize - EfiRomHeader->EfiImageHeaderOffset; if (EfiRomHeader->CompressionType != EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) { // @@ -299,7 +299,7 @@ GetOpRomInfo ( return EFI_NOT_FOUND; } - PciIoDevice->RomSize = (UINT64) ((~AllOnes) + 1); + PciIoDevice->RomSize = (~AllOnes) + 1; return EFI_SUCCESS; } @@ -321,35 +321,45 @@ ContainEfiImage ( { PCI_EXPANSION_ROM_HEADER *RomHeader; PCI_DATA_STRUCTURE *RomPcir; - BOOLEAN FirstCheck; + UINT8 Indicator; - FirstCheck = TRUE; - RomHeader = RomImage; + Indicator = 0; + RomHeader = RomImage; + if (RomHeader == NULL) { + return FALSE; + } - while ((UINT8 *) RomHeader < (UINT8 *) RomImage + RomSize) { + do { if (RomHeader->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) { - if (FirstCheck) { - return FALSE; - } else { - RomHeader = (PCI_EXPANSION_ROM_HEADER *) ((UINT8 *) RomHeader + 512); - continue; - } + RomHeader = (PCI_EXPANSION_ROM_HEADER *) ((UINT8 *) RomHeader + 512); + continue; } - FirstCheck = FALSE; - RomPcir = (PCI_DATA_STRUCTURE *) ((UINT8 *) RomHeader + RomHeader->PcirOffset); + // + // The PCI Data Structure must be DWORD aligned. + // + if (RomHeader->PcirOffset == 0 || + (RomHeader->PcirOffset & 3) != 0 || + (UINT8 *) RomHeader + RomHeader->PcirOffset + sizeof (PCI_DATA_STRUCTURE) > (UINT8 *) RomImage + RomSize) { + break; + } + + RomPcir = (PCI_DATA_STRUCTURE *) ((UINT8 *) RomHeader + RomHeader->PcirOffset); + if (RomPcir->Signature != PCI_DATA_STRUCTURE_SIGNATURE) { + break; + } if (RomPcir->CodeType == PCI_CODE_TYPE_EFI_IMAGE) { return TRUE; } - RomHeader = (PCI_EXPANSION_ROM_HEADER *) ((UINT8 *) RomHeader + RomPcir->Length * 512); - } + Indicator = RomPcir->Indicator; + RomHeader = (PCI_EXPANSION_ROM_HEADER *) ((UINT8 *) RomHeader + RomPcir->ImageLength * 512); + } while (((UINT8 *) RomHeader < (UINT8 *) RomImage + RomSize) && ((Indicator & 0x80) == 0x00)); return FALSE; } - /** Load Option Rom image for specified PCI device. @@ -378,6 +388,7 @@ LoadOpRomImage ( PCI_DATA_STRUCTURE *RomPcir; UINT64 RomSize; UINT64 RomImageSize; + UINT32 LegacyImageLength; UINT8 *RomInMemory; UINT8 CodeType; @@ -430,6 +441,7 @@ LoadOpRomImage ( RomBarOffset = RomBar; RetStatus = EFI_NOT_FOUND; FirstCheck = TRUE; + LegacyImageLength = 0; do { PciDevice->PciRootBridgeIo->Mem.Read ( @@ -452,6 +464,15 @@ LoadOpRomImage ( FirstCheck = FALSE; OffsetPcir = RomHeader->PcirOffset; + // + // If the pointer to the PCI Data Structure is invalid, no further images can be located. + // The PCI Data Structure must be DWORD aligned. + // + if (OffsetPcir == 0 || + (OffsetPcir & 3) != 0 || + RomImageSize + OffsetPcir + sizeof (PCI_DATA_STRUCTURE) > RomSize) { + break; + } PciDevice->PciRootBridgeIo->Mem.Read ( PciDevice->PciRootBridgeIo, EfiPciWidthUint8, @@ -459,8 +480,18 @@ LoadOpRomImage ( sizeof (PCI_DATA_STRUCTURE), (UINT8 *) RomPcir ); + // + // If a valid signature is not present in the PCI Data Structure, no further images can be located. + // + if (RomPcir->Signature != PCI_DATA_STRUCTURE_SIGNATURE) { + break; + } + if (RomImageSize + RomPcir->ImageLength * 512 > RomSize) { + break; + } if (RomPcir->CodeType == PCI_CODE_TYPE_PCAT_IMAGE) { CodeType = PCI_CODE_TYPE_PCAT_IMAGE; + LegacyImageLength = ((UINT32)((EFI_LEGACY_EXPANSION_ROM_HEADER *)RomHeader)->Size512) * 512; } Indicator = RomPcir->Indicator; RomImageSize = RomImageSize + RomPcir->ImageLength * 512; @@ -472,7 +503,7 @@ LoadOpRomImage ( // of the legacy length and the PCIR Image Length // if (CodeType == PCI_CODE_TYPE_PCAT_IMAGE) { - RomImageSize = MAX(RomImageSize, (((EFI_LEGACY_EXPANSION_ROM_HEADER *)RomHeader)->Size512 * 512)); + RomImageSize = MAX (RomImageSize, LegacyImageLength); } if (RomImageSize > 0) { @@ -500,6 +531,7 @@ LoadOpRomImage ( RomDecode (PciDevice, RomBarIndex, RomBar, FALSE); + PciDevice->EmbeddedRom = TRUE; PciDevice->PciIo.RomSize = RomImageSize; PciDevice->PciIo.RomImage = RomInMemory; @@ -513,7 +545,7 @@ LoadOpRomImage ( PciDevice->BusNumber, PciDevice->DeviceNumber, PciDevice->FunctionNumber, - (UINT64) (UINTN) PciDevice->PciIo.RomImage, + PciDevice->PciIo.RomImage, PciDevice->PciIo.RomSize ); @@ -545,17 +577,10 @@ RomDecode ( ) { UINT32 Value32; - UINT32 Offset; EFI_PCI_IO_PROTOCOL *PciIo; PciIo = &PciDevice->PciIo; if (Enable) { - // - // Clear all bars - // - for (Offset = 0x10; Offset <= 0x24; Offset += sizeof (UINT32)) { - PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, Offset, 1, &gAllZero); - } // // set the Rom base address: now is hardcode @@ -573,7 +598,7 @@ RomDecode ( // // Programe all upstream bridge // - ProgrameUpstreamBridgeForRom(PciDevice, RomBar, TRUE); + ProgramUpstreamBridgeForRom (PciDevice, RomBar, TRUE); // // Setting the memory space bit in the function's command register @@ -590,7 +615,7 @@ RomDecode ( // // Destroy the programmed bar in all the upstream bridge. // - ProgrameUpstreamBridgeForRom(PciDevice, RomBar, FALSE); + ProgramUpstreamBridgeForRom (PciDevice, RomBar, FALSE); // // disable rom decode @@ -628,7 +653,6 @@ ProcessOpRomImage ( EFI_HANDLE ImageHandle; EFI_STATUS Status; EFI_STATUS RetStatus; - BOOLEAN FirstCheck; EFI_PCI_EXPANSION_ROM_HEADER *EfiRomHeader; PCI_DATA_STRUCTURE *Pcir; EFI_DEVICE_PATH_PROTOCOL *PciOptionRomImageDevicePath; @@ -644,24 +668,38 @@ ProcessOpRomImage ( RomBar = PciDevice->PciIo.RomImage; RomBarOffset = (UINT8 *) RomBar; RetStatus = EFI_NOT_FOUND; - FirstCheck = TRUE; + + if (RomBar == NULL) { + return RetStatus; + } + ASSERT (((EFI_PCI_EXPANSION_ROM_HEADER *) RomBarOffset)->Signature == PCI_EXPANSION_ROM_HEADER_SIGNATURE); do { EfiRomHeader = (EFI_PCI_EXPANSION_ROM_HEADER *) RomBarOffset; if (EfiRomHeader->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) { RomBarOffset += 512; - if (FirstCheck) { - break; - } else { - continue; - } + continue; } - FirstCheck = FALSE; Pcir = (PCI_DATA_STRUCTURE *) (RomBarOffset + EfiRomHeader->PcirOffset); + ASSERT (Pcir->Signature == PCI_DATA_STRUCTURE_SIGNATURE); ImageSize = (UINT32) (Pcir->ImageLength * 512); Indicator = Pcir->Indicator; + // + // Skip the image if it is not an EFI PCI Option ROM image + // + if (Pcir->CodeType != PCI_CODE_TYPE_EFI_IMAGE) { + goto NextImage; + } + + // + // Ignore the EFI PCI Option ROM image if it is an EFI application + // + if (EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION) { + goto NextImage; + } + // // Create Pci Option Rom Image device path header // @@ -679,56 +717,47 @@ ProcessOpRomImage ( // BufferSize = 0; Buffer = NULL; - Status = EFI_SUCCESS; ImageHandle = NULL; - if (!EFI_ERROR (Status)) { - Status = gBS->LoadImage ( - FALSE, - gPciBusDriverBinding.DriverBindingHandle, - PciOptionRomImageDevicePath, - Buffer, - BufferSize, - &ImageHandle - ); - } - - // - // load image and start image - // - if (!EFI_ERROR (Status)) { - Status = gBS->LoadImage ( - FALSE, - gPciBusDriverBinding.DriverBindingHandle, - PciOptionRomImageDevicePath, - Buffer, - BufferSize, - &ImageHandle - ); - } - - FreePool (PciOptionRomImageDevicePath); - - if (!EFI_ERROR (Status)) { + Status = gBS->LoadImage ( + FALSE, + gPciBusDriverBinding.DriverBindingHandle, + PciOptionRomImageDevicePath, + Buffer, + BufferSize, + &ImageHandle + ); + if (EFI_ERROR (Status)) { + // + // Record the Option ROM Image device path when LoadImage fails. + // PciOverride.GetDriver() will try to look for the Image Handle using the device path later. + // + AddDriver (PciDevice, NULL, PciOptionRomImageDevicePath); + } else { Status = gBS->StartImage (ImageHandle, NULL, NULL); if (!EFI_ERROR (Status)) { - AddDriver (PciDevice, ImageHandle); + // + // Record the Option ROM Image Handle + // + AddDriver (PciDevice, ImageHandle, NULL); PciRomAddImageMapping ( ImageHandle, PciDevice->PciRootBridgeIo->SegmentNumber, PciDevice->BusNumber, PciDevice->DeviceNumber, PciDevice->FunctionNumber, - (UINT64) (UINTN) PciDevice->PciIo.RomImage, + PciDevice->PciIo.RomImage, PciDevice->PciIo.RomSize ); RetStatus = EFI_SUCCESS; } } + FreePool (PciOptionRomImageDevicePath); +NextImage: RomBarOffset += ImageSize; - } while (((Indicator & 0x80) == 0x00) && ((UINTN) (RomBarOffset - (UINT8 *) RomBar) < PciDevice->RomSize)); + } while (((Indicator & 0x80) == 0x00) && (((UINTN) RomBarOffset - (UINTN) RomBar) < PciDevice->RomSize)); return RetStatus; }