]> git.proxmox.com Git - mirror_edk2.git/blobdiff - IntelFrameworkModulePkg/Bus/Pci/PciBusDxe/PciOptionRomSupport.c
Code scrub for PCI Bus module and PciIncompatibleDeviceSupportLib module.
[mirror_edk2.git] / IntelFrameworkModulePkg / Bus / Pci / PciBusDxe / PciOptionRomSupport.c
index 99c34d5bf51f0ea6571a5abf6149a101134f1247..9365847eb55e3178fb063292dd823b2256217d65 100644 (file)
-/**@file\r
+/** @file\r
+  PCI Rom supporting funtions implementation for PCI Bus module.\r
 \r
-Copyright (c) 2006, 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
+Copyright (c) 2006 - 2009, 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
+**/\r
+\r
+#include "PciBus.h"\r
+\r
+/**\r
+  Load the EFI Image from Option ROM\r
+\r
+  @param PciIoDevice   PCI IO device instance.\r
+  @param FilePath      The file path of the EFI Image\r
+  @param BufferSize    On input the size of Buffer in bytes. On output with a return\r
+                       code of EFI_SUCCESS, the amount of data transferred to Buffer.\r
+                       On output with a return code of EFI_BUFFER_TOO_SMALL,\r
+                       the size of Buffer required to retrieve the requested file.\r
+  @param Buffer        The memory buffer to transfer the file to. If Buffer is NULL,\r
+                       then no the size of the requested file is returned in BufferSize.\r
+\r
+  @retval EFI_SUCCESS           The file was loaded.\r
+  @retval EFI_INVALID_PARAMETER FilePath is not a valid device path, or\r
+                                BufferSize is NULL.\r
+  @retval EFI_NOT_FOUND         Not found PCI Option Rom on PCI device.\r
+  @retval EFI_DEVICE_ERROR      Failed to decompress PCI Option Rom image.\r
+  @retval EFI_BUFFER_TOO_SMALL  The BufferSize is too small to read the current directory entry.\r
+                                BufferSize has been updated with the size needed to complete the request.\r
 **/\r
+EFI_STATUS\r
+LocalLoadFile2 (\r
+  IN PCI_IO_DEVICE            *PciIoDevice,\r
+  IN EFI_DEVICE_PATH_PROTOCOL *FilePath,\r
+  IN OUT UINTN                *BufferSize,\r
+  IN VOID                     *Buffer      OPTIONAL\r
+  )\r
+{\r
+  EFI_STATUS                                Status;\r
+  MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH   *EfiOpRomImageNode;\r
+  EFI_PCI_EXPANSION_ROM_HEADER              *EfiRomHeader;\r
+  PCI_DATA_STRUCTURE                        *Pcir;\r
+  UINT32                                    ImageSize;\r
+  UINT8                                     *ImageBuffer;\r
+  UINT32                                    ImageLength;\r
+  UINT32                                    DestinationSize;\r
+  UINT32                                    ScratchSize;\r
+  VOID                                      *Scratch;\r
+  EFI_DECOMPRESS_PROTOCOL                   *Decompress;\r
+\r
+  EfiOpRomImageNode = (MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH *) FilePath;\r
+  if ((EfiOpRomImageNode == NULL) ||\r
+      (DevicePathType (FilePath) != MEDIA_DEVICE_PATH) ||\r
+      (DevicePathSubType (FilePath) != MEDIA_RELATIVE_OFFSET_RANGE_DP) ||\r
+      (DevicePathNodeLength (FilePath) != sizeof (MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH)) ||\r
+      (!IsDevicePathEnd (NextDevicePathNode (FilePath))) ||\r
+      (EfiOpRomImageNode->StartingOffset > EfiOpRomImageNode->EndingOffset) ||\r
+      (EfiOpRomImageNode->EndingOffset >= PciIoDevice->RomSize) ||\r
+      (BufferSize == NULL)\r
+      ) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  EfiRomHeader = (EFI_PCI_EXPANSION_ROM_HEADER *) (\r
+      (UINT8 *) PciIoDevice->PciIo.RomImage + EfiOpRomImageNode->StartingOffset\r
+      );\r
+  if (EfiRomHeader->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+\r
+  Pcir = (PCI_DATA_STRUCTURE *) ((UINT8 *) EfiRomHeader + EfiRomHeader->PcirOffset);\r
+\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
+      (EfiRomHeader->CompressionType <= EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED)\r
+       ) {\r
+\r
+    ImageSize               = (UINT32) EfiRomHeader->InitializationSize * 512;\r
+    ImageBuffer             = (UINT8 *) EfiRomHeader + EfiRomHeader->EfiImageHeaderOffset;\r
+    ImageLength             = ImageSize - EfiRomHeader->EfiImageHeaderOffset;\r
+\r
+    if (EfiRomHeader->CompressionType != EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) {\r
+      //\r
+      // Uncompressed: Copy the EFI Image directly to user's buffer\r
+      //\r
+      if (Buffer == NULL || *BufferSize < ImageLength) {\r
+        *BufferSize = ImageLength;\r
+        return EFI_BUFFER_TOO_SMALL;\r
+      }\r
+\r
+      *BufferSize = ImageLength;\r
+      CopyMem (Buffer, ImageBuffer, ImageLength);\r
+      return EFI_SUCCESS;\r
+\r
+    } else {\r
+      //\r
+      // Compressed: Uncompress before copying\r
+      //\r
+      Status = gBS->LocateProtocol (&gEfiDecompressProtocolGuid, NULL, (VOID **) &Decompress);\r
+      if (EFI_ERROR (Status)) {\r
+        return EFI_DEVICE_ERROR;\r
+      }\r
+      Status = Decompress->GetInfo (\r
+                             Decompress,\r
+                             ImageBuffer,\r
+                             ImageLength,\r
+                             &DestinationSize,\r
+                             &ScratchSize\r
+                             );\r
+      if (EFI_ERROR (Status)) {\r
+        return EFI_DEVICE_ERROR;\r
+      }\r
+\r
+      if (Buffer == NULL || *BufferSize < DestinationSize) {\r
+        *BufferSize = DestinationSize;\r
+        return EFI_BUFFER_TOO_SMALL;\r
+      }\r
+\r
+      *BufferSize = DestinationSize;\r
+      Scratch = AllocatePool (ScratchSize);\r
+      if (Scratch == NULL) {\r
+        return EFI_DEVICE_ERROR;\r
+      }\r
+\r
+      Status = Decompress->Decompress (\r
+                             Decompress,\r
+                             ImageBuffer,\r
+                             ImageLength,\r
+                             Buffer,\r
+                             DestinationSize,\r
+                             Scratch,\r
+                             ScratchSize\r
+                             );\r
+      FreePool (Scratch);\r
+\r
+      if (EFI_ERROR (Status)) {\r
+        return EFI_DEVICE_ERROR;\r
+      }\r
+      return EFI_SUCCESS;\r
+    }\r
+  }\r
+\r
+  return EFI_NOT_FOUND;\r
+}\r
+\r
+/**\r
+  Initialize a PCI LoadFile2 instance.\r
 \r
-#include "pcibus.h"\r
-#include "PciResourceSupport.h"\r
-\r
-#include <IndustryStandard/Pci23.h>\r
-\r
-//\r
-// Module global for a template of the PCI option ROM Image Device Path Node\r
-//\r
-MEMMAP_DEVICE_PATH  mPciOptionRomImageDevicePathNodeTemplate = {\r
-  {                 \r
-    HARDWARE_DEVICE_PATH,\r
-    HW_MEMMAP_DP,\r
-    sizeof (MEMMAP_DEVICE_PATH)\r
-  },\r
-  EfiMemoryMappedIO,\r
-  0,\r
-  0\r
-};\r
+  @param PciIoDevice   PCI IO Device.\r
 \r
+**/\r
+VOID\r
+InitializePciLoadFile2 (\r
+  IN PCI_IO_DEVICE       *PciIoDevice\r
+  )\r
+{\r
+  PciIoDevice->LoadFile2.LoadFile = LoadFile2;\r
+}\r
+\r
+/**\r
+  Causes the driver to load a specified file.\r
+\r
+  @param This        Indicates a pointer to the calling context.\r
+  @param FilePath    The device specific path of the file to load.\r
+  @param BootPolicy  Should always be FALSE.\r
+  @param BufferSize  On input the size of Buffer in bytes. On output with a return\r
+                     code of EFI_SUCCESS, the amount of data transferred to Buffer.\r
+                     On output with a return code of EFI_BUFFER_TOO_SMALL,\r
+                     the size of Buffer required to retrieve the requested file.\r
+  @param Buffer      The memory buffer to transfer the file to. If Buffer is NULL,\r
+                     then no the size of the requested file is returned in BufferSize.\r
+\r
+  @retval EFI_SUCCESS           The file was loaded.\r
+  @retval EFI_UNSUPPORTED       BootPolicy is TRUE.\r
+  @retval EFI_INVALID_PARAMETER FilePath is not a valid device path, or\r
+                                BufferSize is NULL.\r
+  @retval EFI_NOT_FOUND         Not found PCI Option Rom on PCI device.\r
+  @retval EFI_DEVICE_ERROR      Failed to decompress PCI Option Rom image.\r
+  @retval EFI_BUFFER_TOO_SMALL  The BufferSize is too small to read the current directory entry.\r
+                                BufferSize has been updated with the size needed to complete the request.\r
+\r
+**/\r
 EFI_STATUS\r
-GetOpRomInfo (\r
-  IN PCI_IO_DEVICE    *PciIoDevice\r
+EFIAPI\r
+LoadFile2 (\r
+  IN EFI_LOAD_FILE2_PROTOCOL  *This,\r
+  IN EFI_DEVICE_PATH_PROTOCOL *FilePath,\r
+  IN BOOLEAN                  BootPolicy,\r
+  IN OUT UINTN                *BufferSize,\r
+  IN VOID                     *Buffer      OPTIONAL\r
   )\r
-/*++\r
+{\r
+  PCI_IO_DEVICE                             *PciIoDevice;\r
+\r
+  if (BootPolicy) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+  PciIoDevice = PCI_IO_DEVICE_FROM_LOAD_FILE2_THIS (This);\r
+\r
+  return LocalLoadFile2 (\r
+           PciIoDevice,\r
+           FilePath,\r
+           BufferSize,\r
+           Buffer\r
+           );\r
+}\r
 \r
-Routine Description:\r
+/**\r
+  Get Pci device's oprom infor bits.\r
 \r
-Arguments:\r
+  @param PciIoDevice    Pci device instance.\r
 \r
-Returns:\r
+  @retval EFI_NOT_FOUND Pci device has not Option Rom.\r
+  @retval EFI_SUCCESS   Pci device has Option Rom.\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
+EFI_STATUS\r
+GetOpRomInfo (\r
+  IN PCI_IO_DEVICE    *PciIoDevice\r
+  )\r
 {\r
   UINT8                           RomBarIndex;\r
   UINT32                          AllOnes;\r
@@ -63,17 +245,17 @@ Returns:
   PciRootBridgeIo = PciIoDevice->PciRootBridgeIo;\r
 \r
   //\r
-  // offset is 0x30 if is not ppb\r
+  // Offset is 0x30 if is not ppb\r
   //\r
 \r
   //\r
   // 0x30\r
   //\r
-  RomBarIndex = PCI_DEVICE_ROMBAR;\r
+  RomBarIndex = PCI_EXPANSION_ROM_BASE;\r
 \r
   if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {\r
     //\r
-    // if is ppb\r
+    // If is ppb\r
     //\r
 \r
     //\r
@@ -82,7 +264,7 @@ Returns:
     RomBarIndex = PCI_BRIDGE_ROMBAR;\r
   }\r
   //\r
-  // the bit0 is 0 to prevent the enabling of the Rom address decoder\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
@@ -96,11 +278,11 @@ Returns:
                                   &AllOnes\r
                                   );\r
   if (EFI_ERROR (Status)) {\r
-    return Status;\r
+    return EFI_NOT_FOUND;\r
   }\r
 \r
   //\r
-  // read back\r
+  // Read back\r
   //\r
   Status = PciRootBridgeIoRead (\r
                                   PciRootBridgeIo,\r
@@ -111,7 +293,7 @@ Returns:
                                   &AllOnes\r
                                   );\r
   if (EFI_ERROR (Status)) {\r
-    return Status;\r
+    return EFI_NOT_FOUND;\r
   }\r
   //\r
   // Bits [1, 10] are reserved\r
@@ -125,34 +307,75 @@ Returns:
   return EFI_SUCCESS;\r
 }\r
 \r
-EFI_STATUS\r
-LoadOpRomImage (\r
-  IN PCI_IO_DEVICE   *PciDevice,\r
-  IN UINT64          RomBase\r
+/**\r
+  Check if the RomImage contains EFI Images.\r
+\r
+  @param  RomImage  The ROM address of Image for check.\r
+  @param  RomSize   Size of ROM for check.\r
+\r
+  @retval TRUE     ROM contain EFI Image.\r
+  @retval FALSE    ROM not contain EFI Image.\r
+\r
+**/\r
+BOOLEAN\r
+ContainEfiImage (\r
+  IN VOID            *RomImage,\r
+  IN UINT64          RomSize\r
   )\r
-/*++\r
+{\r
+  PCI_EXPANSION_ROM_HEADER  *RomHeader;\r
+  PCI_DATA_STRUCTURE        *RomPcir;\r
+  BOOLEAN                   FirstCheck;\r
+\r
+  FirstCheck = TRUE;\r
+  RomHeader  = RomImage;\r
+\r
+  while ((UINT8 *) RomHeader < (UINT8 *) RomImage + RomSize) {\r
+    if (RomHeader->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) {\r
+      if (FirstCheck) {\r
+        return FALSE;\r
+      } else {\r
+        RomHeader = (PCI_EXPANSION_ROM_HEADER *) ((UINT8 *) RomHeader + 512);\r
+        continue;\r
+      }\r
+    }\r
+\r
+    FirstCheck = FALSE;\r
+    RomPcir    = (PCI_DATA_STRUCTURE *) ((UINT8 *) RomHeader + RomHeader->PcirOffset);\r
+\r
+    if (RomPcir->CodeType == PCI_CODE_TYPE_EFI_IMAGE) {\r
+      return TRUE;\r
+    }\r
+\r
+    RomHeader = (PCI_EXPANSION_ROM_HEADER *) ((UINT8 *) RomHeader + RomPcir->Length * 512);\r
+  }\r
+\r
+  return FALSE;\r
+}\r
 \r
-Routine Description:\r
\r
-    Load option rom image for specified PCI device\r
 \r
-Arguments:\r
+/**\r
+  Load Option Rom image for specified PCI device.\r
 \r
-Returns:\r
+  @param PciDevice Pci device instance.\r
+  @param RomBase   Base address of Option Rom.\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
+  @retval EFI_OUT_OF_RESOURCES No enough memory to hold image.\r
+  @retval EFI_SUCESS           Successfully loaded Option Rom.\r
+\r
+**/\r
+EFI_STATUS\r
+LoadOpRomImage (\r
+  IN PCI_IO_DEVICE   *PciDevice,\r
+  IN UINT64          RomBase\r
+  )\r
 {\r
   UINT8                     RomBarIndex;\r
   UINT8                     Indicator;\r
   UINT16                    OffsetPcir;\r
   UINT32                    RomBarOffset;\r
   UINT32                    RomBar;\r
-  EFI_STATUS                retStatus;\r
+  EFI_STATUS                RetStatus;\r
   BOOLEAN                   FirstCheck;\r
   UINT8                     *Image;\r
   PCI_EXPANSION_ROM_HEADER  *RomHeader;\r
@@ -176,7 +399,7 @@ Returns:
   //\r
   // 0x30\r
   //\r
-  RomBarIndex = PCI_DEVICE_ROMBAR;\r
+  RomBarIndex = PCI_EXPANSION_ROM_BASE;\r
   if (IS_PCI_BRIDGE (&(PciDevice->Pci))) {\r
     //\r
     // if is ppb\r
@@ -197,7 +420,7 @@ Returns:
 \r
   RomPcir = AllocatePool (sizeof (PCI_DATA_STRUCTURE));\r
   if (RomPcir == NULL) {\r
-    gBS->FreePool (RomHeader);\r
+    FreePool (RomHeader);\r
     return EFI_OUT_OF_RESOURCES;\r
   }\r
 \r
@@ -209,7 +432,7 @@ Returns:
   RomDecode (PciDevice, RomBarIndex, RomBar, TRUE);\r
 \r
   RomBarOffset  = RomBar;\r
-  retStatus     = EFI_NOT_FOUND;\r
+  RetStatus     = EFI_NOT_FOUND;\r
   FirstCheck    = TRUE;\r
 \r
   do {\r
@@ -257,15 +480,15 @@ Returns:
   }\r
 \r
   if (RomImageSize > 0) {\r
-    retStatus = EFI_SUCCESS;\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
+      FreePool (RomHeader);\r
+      FreePool (RomPcir);\r
       return EFI_OUT_OF_RESOURCES;\r
     }\r
-    \r
+\r
     //\r
     // Copy Rom image into memory\r
     //\r
@@ -284,6 +507,10 @@ Returns:
   PciDevice->PciIo.RomSize  = RomImageSize;\r
   PciDevice->PciIo.RomImage = RomInMemory;\r
 \r
+  //\r
+  // For OpROM read from PCI device:\r
+  //   Add the Rom Image to internal database for later PCI light enumeration\r
+  //\r
   PciRomAddImageMapping (\r
     NULL,\r
     PciDevice->PciRootBridgeIo->SegmentNumber,\r
@@ -297,33 +524,29 @@ Returns:
   //\r
   // Free allocated memory\r
   //\r
-  gBS->FreePool (RomHeader);\r
-  gBS->FreePool (RomPcir);\r
+  FreePool (RomHeader);\r
+  FreePool (RomPcir);\r
 \r
-  return retStatus;\r
+  return RetStatus;\r
 }\r
 \r
-EFI_STATUS\r
+/**\r
+  Enable/Disable Option Rom decode.\r
+\r
+  @param PciDevice    Pci device instance.\r
+  @param RomBarIndex  The BAR index of the standard PCI Configuration header to use as the\r
+                      base address for resource range. The legal range for this field is 0..5.\r
+  @param RomBar       Base address of Option Rom.\r
+  @param Enable       Flag for enable/disable decode.\r
+\r
+**/\r
+VOID\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
@@ -337,7 +560,7 @@ Returns:
     for (Offset = 0x10; Offset <= 0x24; Offset += sizeof (UINT32)) {\r
       PciIoWrite (PciIo, EfiPciIoWidthUint32, Offset, 1, &gAllZero);\r
     }\r
-    \r
+\r
     //\r
     // set the Rom base address: now is hardcode\r
     // enable its decoder\r
@@ -359,14 +582,14 @@ Returns:
     //\r
     // Setting the memory space bit in the function's command register\r
     //\r
-    PciEnableCommandRegister(PciDevice, EFI_PCI_COMMAND_MEMORY_SPACE);\r
+    PCI_ENABLE_COMMAND_REGISTER(PciDevice, EFI_PCI_COMMAND_MEMORY_SPACE);\r
 \r
   } else {\r
-    \r
+\r
     //\r
     // disable command register decode to memory\r
     //\r
-    PciDisableCommandRegister(PciDevice, EFI_PCI_COMMAND_MEMORY_SPACE);\r
+    PCI_DISABLE_COMMAND_REGISTER(PciDevice, EFI_PCI_COMMAND_MEMORY_SPACE);\r
 \r
     //\r
     // Destroy the programmed bar in all the upstream bridge.\r
@@ -386,65 +609,51 @@ Returns:
                 );\r
 \r
   }\r
+}\r
 \r
-  return EFI_SUCCESS;\r
+/**\r
+  Load and start the Option Rom image.\r
 \r
-}\r
+  @param PciDevice       Pci device instance.\r
+\r
+  @retval EFI_SUCCESS    Successfully loaded and started PCI Option Rom image.\r
+  @retval EFI_NOT_FOUND  Failed to process PCI Option Rom image.\r
 \r
+**/\r
 EFI_STATUS\r
 ProcessOpRomImage (\r
-  PCI_IO_DEVICE   *PciDevice\r
+  IN  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
-  EFI_DEVICE_PATH_PROTOCOL      *PciOptionRomImageDevicePath;\r
+  UINT8                                    Indicator;\r
+  UINT32                                   ImageSize;\r
+  VOID                                     *RomBar;\r
+  UINT8                                    *RomBarOffset;\r
+  EFI_HANDLE                               ImageHandle;\r
+  EFI_STATUS                               Status;\r
+  EFI_STATUS                               RetStatus;\r
+  BOOLEAN                                  FirstCheck;\r
+  EFI_PCI_EXPANSION_ROM_HEADER             *EfiRomHeader;\r
+  PCI_DATA_STRUCTURE                       *Pcir;\r
+  EFI_DEVICE_PATH_PROTOCOL                 *PciOptionRomImageDevicePath;\r
+  MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH  EfiOpRomImageNode;\r
+  VOID                                     *Buffer;\r
+  UINTN                                    BufferSize;\r
 \r
   Indicator = 0;\r
 \r
   //\r
-  // Get the Address of the Rom image\r
+  // Get the Address of the Option Rom image\r
   //\r
   RomBar        = PciDevice->PciIo.RomImage;\r
   RomBarOffset  = (UINT8 *) RomBar;\r
-  retStatus     = EFI_NOT_FOUND;\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
+      RomBarOffset += 512;\r
       if (FirstCheck) {\r
         break;\r
       } else {\r
@@ -457,122 +666,74 @@ Returns:
     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
-          // Build full device path to the PCI Option ROM Image being loaded\r
-          //\r
-          mPciOptionRomImageDevicePathNodeTemplate.StartingAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)RomBarOffset;\r
-          mPciOptionRomImageDevicePathNodeTemplate.EndingAddress   = (EFI_PHYSICAL_ADDRESS)(UINTN)(RomBarOffset + ImageSize - 1);\r
-          PciOptionRomImageDevicePath = AppendDevicePathNode (PciDevice->DevicePath, (const EFI_DEVICE_PATH_PROTOCOL *)&mPciOptionRomImageDevicePathNodeTemplate);\r
-          ASSERT (PciOptionRomImageDevicePath != NULL);\r
-\r
-          //\r
-          // load image and start image\r
-          //\r
-          Status = gBS->LoadImage (\r
-                          FALSE,\r
-                          gPciBusDriverBinding.DriverBindingHandle,\r
-                          PciOptionRomImageDevicePath,\r
-                          ImageBuffer,\r
-                          ImageLength,\r
-                          &ImageHandle\r
-                          );\r
-\r
-          //\r
-          // Free the device path after it has been used by LoadImage\r
-          //\r
-          gBS->FreePool (PciOptionRomImageDevicePath);\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
+    // Create Pci Option Rom Image device path header\r
+    //\r
+    EfiOpRomImageNode.Header.Type     = MEDIA_DEVICE_PATH;\r
+    EfiOpRomImageNode.Header.SubType  = MEDIA_RELATIVE_OFFSET_RANGE_DP;\r
+    SetDevicePathNodeLength (&EfiOpRomImageNode.Header, sizeof (EfiOpRomImageNode));\r
+    EfiOpRomImageNode.StartingOffset  = (UINTN) RomBarOffset - (UINTN) RomBar;\r
+    EfiOpRomImageNode.EndingOffset    = (UINTN) RomBarOffset + ImageSize - 1 - (UINTN) RomBar;\r
 \r
-        RomBarOffset = RomBarOffset + ImageSize;\r
-      } else {\r
-        RomBarOffset = RomBarOffset + ImageSize;\r
+    PciOptionRomImageDevicePath = AppendDevicePathNode (PciDevice->DevicePath, &EfiOpRomImageNode.Header);\r
+    ASSERT (PciOptionRomImageDevicePath != NULL);\r
+\r
+    //\r
+    // load image and start image\r
+    //\r
+    BufferSize  = 0;\r
+    Buffer      = NULL;\r
+    Status      = EFI_SUCCESS;\r
+    ImageHandle = NULL;\r
+\r
+    if (!EFI_ERROR (Status)) {\r
+      Status = gBS->LoadImage (\r
+                      FALSE,\r
+                      gPciBusDriverBinding.DriverBindingHandle,\r
+                      PciOptionRomImageDevicePath,\r
+                      Buffer,\r
+                      BufferSize,\r
+                      &ImageHandle\r
+                      );\r
+    }\r
+\r
+    //\r
+    // load image and start image\r
+    //\r
+     if (!EFI_ERROR (Status)) {\r
+      Status = gBS->LoadImage (\r
+                      FALSE,\r
+                      gPciBusDriverBinding.DriverBindingHandle,\r
+                      PciOptionRomImageDevicePath,\r
+                      Buffer,\r
+                      BufferSize,\r
+                      &ImageHandle\r
+                      );\r
+    }\r
+\r
+    FreePool (PciOptionRomImageDevicePath);\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
-    } else {\r
-      RomBarOffset = RomBarOffset + ImageSize;\r
     }\r
 \r
-  } while (((Indicator & 0x80) == 0x00) && ((UINTN) (RomBarOffset - (UINT8 *) RomBar) < PciDevice->RomSize));\r
+    RomBarOffset += ImageSize;\r
 \r
-  return retStatus;\r
+  } while (((Indicator & 0x80) == 0x00) && ((UINTN) (RomBarOffset - (UINT8 *) RomBar) < PciDevice->RomSize));\r
 \r
+  return RetStatus;\r
 }\r
+\r