2 PCI Rom supporting funtions implementation for PCI Bus module.
\r
4 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
\r
5 This program and the accompanying materials
\r
6 are licensed and made available under the terms and conditions of the BSD License
\r
7 which accompanies this distribution. The full text of the license may be found at
\r
8 http://opensource.org/licenses/bsd-license.php
\r
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
\r
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
\r
18 Load the EFI Image from Option ROM
\r
20 @param PciIoDevice PCI IO device instance.
\r
21 @param FilePath The file path of the EFI Image
\r
22 @param BufferSize On input the size of Buffer in bytes. On output with a return
\r
23 code of EFI_SUCCESS, the amount of data transferred to Buffer.
\r
24 On output with a return code of EFI_BUFFER_TOO_SMALL,
\r
25 the size of Buffer required to retrieve the requested file.
\r
26 @param Buffer The memory buffer to transfer the file to. If Buffer is NULL,
\r
27 then no the size of the requested file is returned in BufferSize.
\r
29 @retval EFI_SUCCESS The file was loaded.
\r
30 @retval EFI_INVALID_PARAMETER FilePath is not a valid device path, or
\r
32 @retval EFI_NOT_FOUND Not found PCI Option Rom on PCI device.
\r
33 @retval EFI_DEVICE_ERROR Failed to decompress PCI Option Rom image.
\r
34 @retval EFI_BUFFER_TOO_SMALL The BufferSize is too small to read the current directory entry.
\r
35 BufferSize has been updated with the size needed to complete the request.
\r
39 IN PCI_IO_DEVICE *PciIoDevice,
\r
40 IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
\r
41 IN OUT UINTN *BufferSize,
\r
42 IN VOID *Buffer OPTIONAL
\r
46 MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH *EfiOpRomImageNode;
\r
47 EFI_PCI_EXPANSION_ROM_HEADER *EfiRomHeader;
\r
48 PCI_DATA_STRUCTURE *Pcir;
\r
52 UINT32 DestinationSize;
\r
55 EFI_DECOMPRESS_PROTOCOL *Decompress;
\r
56 UINT32 InitializationSize;
\r
58 EfiOpRomImageNode = (MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH *) FilePath;
\r
59 if ((EfiOpRomImageNode == NULL) ||
\r
60 (DevicePathType (FilePath) != MEDIA_DEVICE_PATH) ||
\r
61 (DevicePathSubType (FilePath) != MEDIA_RELATIVE_OFFSET_RANGE_DP) ||
\r
62 (DevicePathNodeLength (FilePath) != sizeof (MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH)) ||
\r
63 (!IsDevicePathEnd (NextDevicePathNode (FilePath))) ||
\r
64 (EfiOpRomImageNode->StartingOffset > EfiOpRomImageNode->EndingOffset) ||
\r
65 (EfiOpRomImageNode->EndingOffset >= PciIoDevice->RomSize) ||
\r
66 (BufferSize == NULL)
\r
68 return EFI_INVALID_PARAMETER;
\r
71 EfiRomHeader = (EFI_PCI_EXPANSION_ROM_HEADER *) (
\r
72 (UINT8 *) PciIoDevice->PciIo.RomImage + EfiOpRomImageNode->StartingOffset
\r
74 if (EfiRomHeader->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) {
\r
75 return EFI_NOT_FOUND;
\r
79 Pcir = (PCI_DATA_STRUCTURE *) ((UINT8 *) EfiRomHeader + EfiRomHeader->PcirOffset);
\r
80 ASSERT (Pcir->Signature == PCI_DATA_STRUCTURE_SIGNATURE);
\r
82 if ((Pcir->CodeType == PCI_CODE_TYPE_EFI_IMAGE) &&
\r
83 (EfiRomHeader->EfiSignature == EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE) &&
\r
84 ((EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER) ||
\r
85 (EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER)) &&
\r
86 (EfiRomHeader->CompressionType <= EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED)
\r
89 ImageSize = Pcir->ImageLength * 512;
\r
90 InitializationSize = (UINT32) EfiRomHeader->InitializationSize * 512;
\r
91 if (InitializationSize > ImageSize || EfiRomHeader->EfiImageHeaderOffset >= InitializationSize) {
\r
92 return EFI_NOT_FOUND;
\r
95 ImageBuffer = (UINT8 *) EfiRomHeader + EfiRomHeader->EfiImageHeaderOffset;
\r
96 ImageLength = InitializationSize - EfiRomHeader->EfiImageHeaderOffset;
\r
98 if (EfiRomHeader->CompressionType != EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) {
\r
100 // Uncompressed: Copy the EFI Image directly to user's buffer
\r
102 if (Buffer == NULL || *BufferSize < ImageLength) {
\r
103 *BufferSize = ImageLength;
\r
104 return EFI_BUFFER_TOO_SMALL;
\r
107 *BufferSize = ImageLength;
\r
108 CopyMem (Buffer, ImageBuffer, ImageLength);
\r
109 return EFI_SUCCESS;
\r
113 // Compressed: Uncompress before copying
\r
115 Status = gBS->LocateProtocol (&gEfiDecompressProtocolGuid, NULL, (VOID **) &Decompress);
\r
116 if (EFI_ERROR (Status)) {
\r
117 return EFI_DEVICE_ERROR;
\r
119 Status = Decompress->GetInfo (
\r
126 if (EFI_ERROR (Status)) {
\r
127 return EFI_DEVICE_ERROR;
\r
130 if (Buffer == NULL || *BufferSize < DestinationSize) {
\r
131 *BufferSize = DestinationSize;
\r
132 return EFI_BUFFER_TOO_SMALL;
\r
135 *BufferSize = DestinationSize;
\r
136 Scratch = AllocatePool (ScratchSize);
\r
137 if (Scratch == NULL) {
\r
138 return EFI_DEVICE_ERROR;
\r
141 Status = Decompress->Decompress (
\r
150 FreePool (Scratch);
\r
152 if (EFI_ERROR (Status)) {
\r
153 return EFI_DEVICE_ERROR;
\r
155 return EFI_SUCCESS;
\r
159 return EFI_NOT_FOUND;
\r
163 Initialize a PCI LoadFile2 instance.
\r
165 @param PciIoDevice PCI IO Device.
\r
169 InitializePciLoadFile2 (
\r
170 IN PCI_IO_DEVICE *PciIoDevice
\r
173 PciIoDevice->LoadFile2.LoadFile = LoadFile2;
\r
177 Causes the driver to load a specified file.
\r
179 @param This Indicates a pointer to the calling context.
\r
180 @param FilePath The device specific path of the file to load.
\r
181 @param BootPolicy Should always be FALSE.
\r
182 @param BufferSize On input the size of Buffer in bytes. On output with a return
\r
183 code of EFI_SUCCESS, the amount of data transferred to Buffer.
\r
184 On output with a return code of EFI_BUFFER_TOO_SMALL,
\r
185 the size of Buffer required to retrieve the requested file.
\r
186 @param Buffer The memory buffer to transfer the file to. If Buffer is NULL,
\r
187 then no the size of the requested file is returned in BufferSize.
\r
189 @retval EFI_SUCCESS The file was loaded.
\r
190 @retval EFI_UNSUPPORTED BootPolicy is TRUE.
\r
191 @retval EFI_INVALID_PARAMETER FilePath is not a valid device path, or
\r
192 BufferSize is NULL.
\r
193 @retval EFI_NOT_FOUND Not found PCI Option Rom on PCI device.
\r
194 @retval EFI_DEVICE_ERROR Failed to decompress PCI Option Rom image.
\r
195 @retval EFI_BUFFER_TOO_SMALL The BufferSize is too small to read the current directory entry.
\r
196 BufferSize has been updated with the size needed to complete the request.
\r
202 IN EFI_LOAD_FILE2_PROTOCOL *This,
\r
203 IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
\r
204 IN BOOLEAN BootPolicy,
\r
205 IN OUT UINTN *BufferSize,
\r
206 IN VOID *Buffer OPTIONAL
\r
209 PCI_IO_DEVICE *PciIoDevice;
\r
212 return EFI_UNSUPPORTED;
\r
214 PciIoDevice = PCI_IO_DEVICE_FROM_LOAD_FILE2_THIS (This);
\r
216 return LocalLoadFile2 (
\r
225 Get Pci device's oprom information.
\r
227 @param PciIoDevice Input Pci device instance.
\r
228 Output Pci device instance with updated OptionRom size.
\r
230 @retval EFI_NOT_FOUND Pci device has not Option Rom.
\r
231 @retval EFI_SUCCESS Pci device has Option Rom.
\r
236 IN OUT PCI_IO_DEVICE *PciIoDevice
\r
246 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
\r
248 Bus = PciIoDevice->BusNumber;
\r
249 Device = PciIoDevice->DeviceNumber;
\r
250 Function = PciIoDevice->FunctionNumber;
\r
252 PciRootBridgeIo = PciIoDevice->PciRootBridgeIo;
\r
255 // Offset is 0x30 if is not ppb
\r
261 RomBarIndex = PCI_EXPANSION_ROM_BASE;
\r
263 if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {
\r
267 RomBarIndex = PCI_BRIDGE_ROMBAR;
\r
270 // The bit0 is 0 to prevent the enabling of the Rom address decoder
\r
272 AllOnes = 0xfffffffe;
\r
273 Address = EFI_PCI_ADDRESS (Bus, Device, Function, RomBarIndex);
\r
275 Status = PciRootBridgeIo->Pci.Write (
\r
282 if (EFI_ERROR (Status)) {
\r
283 return EFI_NOT_FOUND;
\r
289 Status = PciRootBridgeIo->Pci.Read(
\r
296 if (EFI_ERROR (Status)) {
\r
297 return EFI_NOT_FOUND;
\r
301 // Bits [1, 10] are reserved
\r
303 AllOnes &= 0xFFFFF800;
\r
304 if ((AllOnes == 0) || (AllOnes == 0xFFFFF800)) {
\r
305 return EFI_NOT_FOUND;
\r
308 PciIoDevice->RomSize = (~AllOnes) + 1;
\r
309 return EFI_SUCCESS;
\r
313 Check if the RomImage contains EFI Images.
\r
315 @param RomImage The ROM address of Image for check.
\r
316 @param RomSize Size of ROM for check.
\r
318 @retval TRUE ROM contain EFI Image.
\r
319 @retval FALSE ROM not contain EFI Image.
\r
328 PCI_EXPANSION_ROM_HEADER *RomHeader;
\r
329 PCI_DATA_STRUCTURE *RomPcir;
\r
333 RomHeader = RomImage;
\r
334 if (RomHeader == NULL) {
\r
339 if (RomHeader->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) {
\r
340 RomHeader = (PCI_EXPANSION_ROM_HEADER *) ((UINT8 *) RomHeader + 512);
\r
345 // The PCI Data Structure must be DWORD aligned.
\r
347 if (RomHeader->PcirOffset == 0 ||
\r
348 (RomHeader->PcirOffset & 3) != 0 ||
\r
349 (UINT8 *) RomHeader + RomHeader->PcirOffset + sizeof (PCI_DATA_STRUCTURE) > (UINT8 *) RomImage + RomSize) {
\r
353 RomPcir = (PCI_DATA_STRUCTURE *) ((UINT8 *) RomHeader + RomHeader->PcirOffset);
\r
354 if (RomPcir->Signature != PCI_DATA_STRUCTURE_SIGNATURE) {
\r
358 if (RomPcir->CodeType == PCI_CODE_TYPE_EFI_IMAGE) {
\r
362 Indicator = RomPcir->Indicator;
\r
363 RomHeader = (PCI_EXPANSION_ROM_HEADER *) ((UINT8 *) RomHeader + RomPcir->ImageLength * 512);
\r
364 } while (((UINT8 *) RomHeader < (UINT8 *) RomImage + RomSize) && ((Indicator & 0x80) == 0x00));
\r
370 Load Option Rom image for specified PCI device.
\r
372 @param PciDevice Pci device instance.
\r
373 @param RomBase Base address of Option Rom.
\r
375 @retval EFI_OUT_OF_RESOURCES No enough memory to hold image.
\r
376 @retval EFI_SUCESS Successfully loaded Option Rom.
\r
381 IN PCI_IO_DEVICE *PciDevice,
\r
388 UINT32 RomBarOffset;
\r
390 EFI_STATUS RetStatus;
\r
391 BOOLEAN FirstCheck;
\r
393 PCI_EXPANSION_ROM_HEADER *RomHeader;
\r
394 PCI_DATA_STRUCTURE *RomPcir;
\r
396 UINT64 RomImageSize;
\r
397 UINT32 LegacyImageLength;
\r
398 UINT8 *RomInMemory;
\r
401 RomSize = PciDevice->RomSize;
\r
405 RomInMemory = NULL;
\r
409 // Get the RomBarIndex
\r
415 RomBarIndex = PCI_EXPANSION_ROM_BASE;
\r
416 if (IS_PCI_BRIDGE (&(PciDevice->Pci))) {
\r
424 RomBarIndex = PCI_BRIDGE_ROMBAR;
\r
427 // Allocate memory for Rom header and PCIR
\r
429 RomHeader = AllocatePool (sizeof (PCI_EXPANSION_ROM_HEADER));
\r
430 if (RomHeader == NULL) {
\r
431 return EFI_OUT_OF_RESOURCES;
\r
434 RomPcir = AllocatePool (sizeof (PCI_DATA_STRUCTURE));
\r
435 if (RomPcir == NULL) {
\r
436 FreePool (RomHeader);
\r
437 return EFI_OUT_OF_RESOURCES;
\r
440 RomBar = (UINT32) RomBase;
\r
445 RomDecode (PciDevice, RomBarIndex, RomBar, TRUE);
\r
447 RomBarOffset = RomBar;
\r
448 RetStatus = EFI_NOT_FOUND;
\r
450 LegacyImageLength = 0;
\r
453 PciDevice->PciRootBridgeIo->Mem.Read (
\r
454 PciDevice->PciRootBridgeIo,
\r
457 sizeof (PCI_EXPANSION_ROM_HEADER),
\r
458 (UINT8 *) RomHeader
\r
461 if (RomHeader->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) {
\r
462 RomBarOffset = RomBarOffset + 512;
\r
466 RomImageSize = RomImageSize + 512;
\r
471 FirstCheck = FALSE;
\r
472 OffsetPcir = RomHeader->PcirOffset;
\r
474 // If the pointer to the PCI Data Structure is invalid, no further images can be located.
\r
475 // The PCI Data Structure must be DWORD aligned.
\r
477 if (OffsetPcir == 0 ||
\r
478 (OffsetPcir & 3) != 0 ||
\r
479 RomImageSize + OffsetPcir + sizeof (PCI_DATA_STRUCTURE) > RomSize) {
\r
482 PciDevice->PciRootBridgeIo->Mem.Read (
\r
483 PciDevice->PciRootBridgeIo,
\r
485 RomBarOffset + OffsetPcir,
\r
486 sizeof (PCI_DATA_STRUCTURE),
\r
490 // If a valid signature is not present in the PCI Data Structure, no further images can be located.
\r
492 if (RomPcir->Signature != PCI_DATA_STRUCTURE_SIGNATURE) {
\r
495 if (RomImageSize + RomPcir->ImageLength * 512 > RomSize) {
\r
498 if (RomPcir->CodeType == PCI_CODE_TYPE_PCAT_IMAGE) {
\r
499 CodeType = PCI_CODE_TYPE_PCAT_IMAGE;
\r
500 LegacyImageLength = ((UINT32)((EFI_LEGACY_EXPANSION_ROM_HEADER *)RomHeader)->Size512) * 512;
\r
502 Indicator = RomPcir->Indicator;
\r
503 RomImageSize = RomImageSize + RomPcir->ImageLength * 512;
\r
504 RomBarOffset = RomBarOffset + RomPcir->ImageLength * 512;
\r
505 } while (((Indicator & 0x80) == 0x00) && ((RomBarOffset - RomBar) < RomSize));
\r
508 // Some Legacy Cards do not report the correct ImageLength so used the maximum
\r
509 // of the legacy length and the PCIR Image Length
\r
511 if (CodeType == PCI_CODE_TYPE_PCAT_IMAGE) {
\r
512 RomImageSize = MAX (RomImageSize, LegacyImageLength);
\r
515 if (RomImageSize > 0) {
\r
516 RetStatus = EFI_SUCCESS;
\r
517 Image = AllocatePool ((UINT32) RomImageSize);
\r
518 if (Image == NULL) {
\r
519 RomDecode (PciDevice, RomBarIndex, RomBar, FALSE);
\r
520 FreePool (RomHeader);
\r
521 FreePool (RomPcir);
\r
522 return EFI_OUT_OF_RESOURCES;
\r
526 // Copy Rom image into memory
\r
528 PciDevice->PciRootBridgeIo->Mem.Read (
\r
529 PciDevice->PciRootBridgeIo,
\r
532 (UINT32) RomImageSize,
\r
535 RomInMemory = Image;
\r
538 RomDecode (PciDevice, RomBarIndex, RomBar, FALSE);
\r
540 PciDevice->EmbeddedRom = TRUE;
\r
541 PciDevice->PciIo.RomSize = RomImageSize;
\r
542 PciDevice->PciIo.RomImage = RomInMemory;
\r
545 // For OpROM read from PCI device:
\r
546 // Add the Rom Image to internal database for later PCI light enumeration
\r
548 PciRomAddImageMapping (
\r
550 PciDevice->PciRootBridgeIo->SegmentNumber,
\r
551 PciDevice->BusNumber,
\r
552 PciDevice->DeviceNumber,
\r
553 PciDevice->FunctionNumber,
\r
554 PciDevice->PciIo.RomImage,
\r
555 PciDevice->PciIo.RomSize
\r
559 // Free allocated memory
\r
561 FreePool (RomHeader);
\r
562 FreePool (RomPcir);
\r
568 Enable/Disable Option Rom decode.
\r
570 @param PciDevice Pci device instance.
\r
571 @param RomBarIndex The BAR index of the standard PCI Configuration header to use as the
\r
572 base address for resource range. The legal range for this field is 0..5.
\r
573 @param RomBar Base address of Option Rom.
\r
574 @param Enable Flag for enable/disable decode.
\r
579 IN PCI_IO_DEVICE *PciDevice,
\r
580 IN UINT8 RomBarIndex,
\r
586 EFI_PCI_IO_PROTOCOL *PciIo;
\r
588 PciIo = &PciDevice->PciIo;
\r
592 // set the Rom base address: now is hardcode
\r
593 // enable its decoder
\r
595 Value32 = RomBar | 0x1;
\r
598 (EFI_PCI_IO_PROTOCOL_WIDTH) EfiPciWidthUint32,
\r
605 // Programe all upstream bridge
\r
607 ProgrameUpstreamBridgeForRom(PciDevice, RomBar, TRUE);
\r
610 // Setting the memory space bit in the function's command register
\r
612 PCI_ENABLE_COMMAND_REGISTER(PciDevice, EFI_PCI_COMMAND_MEMORY_SPACE);
\r
617 // disable command register decode to memory
\r
619 PCI_DISABLE_COMMAND_REGISTER(PciDevice, EFI_PCI_COMMAND_MEMORY_SPACE);
\r
622 // Destroy the programmed bar in all the upstream bridge.
\r
624 ProgrameUpstreamBridgeForRom(PciDevice, RomBar, FALSE);
\r
627 // disable rom decode
\r
629 Value32 = 0xFFFFFFFE;
\r
632 (EFI_PCI_IO_PROTOCOL_WIDTH) EfiPciWidthUint32,
\r
642 Load and start the Option Rom image.
\r
644 @param PciDevice Pci device instance.
\r
646 @retval EFI_SUCCESS Successfully loaded and started PCI Option Rom image.
\r
647 @retval EFI_NOT_FOUND Failed to process PCI Option Rom image.
\r
651 ProcessOpRomImage (
\r
652 IN PCI_IO_DEVICE *PciDevice
\r
658 UINT8 *RomBarOffset;
\r
659 EFI_HANDLE ImageHandle;
\r
661 EFI_STATUS RetStatus;
\r
662 EFI_PCI_EXPANSION_ROM_HEADER *EfiRomHeader;
\r
663 PCI_DATA_STRUCTURE *Pcir;
\r
664 EFI_DEVICE_PATH_PROTOCOL *PciOptionRomImageDevicePath;
\r
665 MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH EfiOpRomImageNode;
\r
672 // Get the Address of the Option Rom image
\r
674 RomBar = PciDevice->PciIo.RomImage;
\r
675 RomBarOffset = (UINT8 *) RomBar;
\r
676 RetStatus = EFI_NOT_FOUND;
\r
678 if (RomBar == NULL) {
\r
681 ASSERT (((EFI_PCI_EXPANSION_ROM_HEADER *) RomBarOffset)->Signature == PCI_EXPANSION_ROM_HEADER_SIGNATURE);
\r
684 EfiRomHeader = (EFI_PCI_EXPANSION_ROM_HEADER *) RomBarOffset;
\r
685 if (EfiRomHeader->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) {
\r
686 RomBarOffset += 512;
\r
690 Pcir = (PCI_DATA_STRUCTURE *) (RomBarOffset + EfiRomHeader->PcirOffset);
\r
691 ASSERT (Pcir->Signature == PCI_DATA_STRUCTURE_SIGNATURE);
\r
692 ImageSize = (UINT32) (Pcir->ImageLength * 512);
\r
693 Indicator = Pcir->Indicator;
\r
696 // Skip the image if it is not an EFI PCI Option ROM image
\r
698 if (Pcir->CodeType != PCI_CODE_TYPE_EFI_IMAGE) {
\r
703 // Skip the EFI PCI Option ROM image if its machine type is not supported
\r
705 if (!EFI_IMAGE_MACHINE_TYPE_SUPPORTED (EfiRomHeader->EfiMachineType)) {
\r
710 // Ignore the EFI PCI Option ROM image if it is an EFI application
\r
712 if (EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION) {
\r
717 // Create Pci Option Rom Image device path header
\r
719 EfiOpRomImageNode.Header.Type = MEDIA_DEVICE_PATH;
\r
720 EfiOpRomImageNode.Header.SubType = MEDIA_RELATIVE_OFFSET_RANGE_DP;
\r
721 SetDevicePathNodeLength (&EfiOpRomImageNode.Header, sizeof (EfiOpRomImageNode));
\r
722 EfiOpRomImageNode.StartingOffset = (UINTN) RomBarOffset - (UINTN) RomBar;
\r
723 EfiOpRomImageNode.EndingOffset = (UINTN) RomBarOffset + ImageSize - 1 - (UINTN) RomBar;
\r
725 PciOptionRomImageDevicePath = AppendDevicePathNode (PciDevice->DevicePath, &EfiOpRomImageNode.Header);
\r
726 ASSERT (PciOptionRomImageDevicePath != NULL);
\r
729 // load image and start image
\r
733 ImageHandle = NULL;
\r
735 Status = gBS->LoadImage (
\r
737 gPciBusDriverBinding.DriverBindingHandle,
\r
738 PciOptionRomImageDevicePath,
\r
743 if (EFI_ERROR (Status)) {
\r
745 // Record the Option ROM Image device path when LoadImage fails.
\r
746 // PciOverride.GetDriver() will try to look for the Image Handle using the device path later.
\r
748 AddDriver (PciDevice, NULL, PciOptionRomImageDevicePath);
\r
750 Status = gBS->StartImage (ImageHandle, NULL, NULL);
\r
751 if (!EFI_ERROR (Status)) {
\r
753 // Record the Option ROM Image Handle
\r
755 AddDriver (PciDevice, ImageHandle, NULL);
\r
756 PciRomAddImageMapping (
\r
758 PciDevice->PciRootBridgeIo->SegmentNumber,
\r
759 PciDevice->BusNumber,
\r
760 PciDevice->DeviceNumber,
\r
761 PciDevice->FunctionNumber,
\r
762 PciDevice->PciIo.RomImage,
\r
763 PciDevice->PciIo.RomSize
\r
765 RetStatus = EFI_SUCCESS;
\r
768 FreePool (PciOptionRomImageDevicePath);
\r
771 RomBarOffset += ImageSize;
\r
773 } while (((Indicator & 0x80) == 0x00) && (((UINTN) RomBarOffset - (UINTN) RomBar) < PciDevice->RomSize));
\r