Home | History | Annotate | Download | only in DeviceIoOnPciRootBridgeIoThunk
      1 /** @file
      2 Module produces Device I/O on top of PCI Root Bridge I/O for Segment 0 only.
      3 This is a valid assumption because many of the EFI 1.02/EFI 1.10 systems that may have provided
      4 Device I/O were single segment platforms.  The goal of the ECP is to provide compatibility with the
      5 drivers/apps that may have used Device I/O.
      6 
      7 Device I/O is on list of deprecated protocols for UEFI 2.0 and later.
      8 This module module layers Device I/O on top of PCI Root Bridge I/O (Segment 0)
      9  Use if:
     10    There are no EDK modules present that produces Device I/O
     11    EFI drivers included that consume Device I/O
     12    Platform required to support EFI drivers that consume Device I/O
     13    Platform required to support EFI applications that consume Device I/O
     14 
     15 Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.<BR>
     16 This program and the accompanying materials
     17 are licensed and made available under the terms and conditions of the BSD License
     18 which accompanies this distribution.  The full text of the license may be found at
     19 http://opensource.org/licenses/bsd-license.php
     20 
     21 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     22 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     23 
     24 **/
     25 
     26 #include <PiDxe.h>
     27 #include <IndustryStandard/Pci.h>
     28 #include <Protocol/DeviceIo.h>
     29 #include <Protocol/PciRootBridgeIo.h>
     30 #include <Library/BaseLib.h>
     31 #include <Library/BaseMemoryLib.h>
     32 #include <Library/DebugLib.h>
     33 #include <Library/UefiBootServicesTableLib.h>
     34 #include <Library/UefiDriverEntryPoint.h>
     35 #include <Library/UefiLib.h>
     36 #include <Library/MemoryAllocationLib.h>
     37 #include <Library/DevicePathLib.h>
     38 
     39 
     40 /**
     41   Perform reading memory mapped I/O space of device.
     42 
     43   @param  This                   A pointer to EFI_DEVICE_IO protocol instance.
     44   @param  Width                  Width of I/O operations.
     45   @param  Address                The base address of I/O operations.
     46   @param  Count                  The number of I/O operations to perform.  Bytes
     47                                  moves is Width size * Count, starting at Address.
     48   @param  Buffer                 The destination buffer to store results.
     49 
     50   @retval EFI_SUCCESS            The data was read from the device.
     51   @retval EFI_INVALID_PARAMETER  Width is invalid.
     52   @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to lack of
     53                                  resources.
     54 
     55 **/
     56 EFI_STATUS
     57 EFIAPI
     58 DeviceIoMemRead (
     59   IN     EFI_DEVICE_IO_PROTOCOL   *This,
     60   IN     EFI_IO_WIDTH             Width,
     61   IN     UINT64                   Address,
     62   IN     UINTN                    Count,
     63   IN OUT VOID                     *Buffer
     64   );
     65 
     66 
     67 /**
     68   Perform writing memory mapped I/O space of device.
     69 
     70   @param  This                   A pointer to EFI_DEVICE_IO protocol instance.
     71   @param  Width                  Width of I/O operations.
     72   @param  Address                The base address of I/O operations.
     73   @param  Count                  The number of I/O operations to perform.  Bytes
     74                                  moves is Width size * Count, starting at Address.
     75   @param  Buffer                 The source buffer of data to be written.
     76 
     77   @retval EFI_SUCCESS            The data was written to the device.
     78   @retval EFI_INVALID_PARAMETER  Width is invalid.
     79   @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to lack of
     80                                  resources.
     81 
     82 **/
     83 EFI_STATUS
     84 EFIAPI
     85 DeviceIoMemWrite (
     86   IN     EFI_DEVICE_IO_PROTOCOL    *This,
     87   IN     EFI_IO_WIDTH              Width,
     88   IN     UINT64                    Address,
     89   IN     UINTN                     Count,
     90   IN OUT VOID                      *Buffer
     91   );
     92 
     93 /**
     94   Perform reading I/O space of device.
     95 
     96   @param  This                   A pointer to EFI_DEVICE_IO protocol instance.
     97   @param  Width                  Width of I/O operations.
     98   @param  Address                The base address of I/O operations.
     99   @param  Count                  The number of I/O operations to perform.  Bytes
    100                                  moves is Width size * Count, starting at Address.
    101   @param  Buffer                 The destination buffer to store results.
    102 
    103   @retval EFI_SUCCESS            The data was read from the device.
    104   @retval EFI_INVALID_PARAMETER  Width is invalid.
    105   @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to lack of
    106                                  resources.
    107 
    108 **/
    109 EFI_STATUS
    110 EFIAPI
    111 DeviceIoIoRead (
    112   IN     EFI_DEVICE_IO_PROTOCOL   *This,
    113   IN     EFI_IO_WIDTH             Width,
    114   IN     UINT64                   Address,
    115   IN     UINTN                    Count,
    116   IN OUT VOID                     *Buffer
    117   );
    118 
    119 /**
    120   Perform writing I/O space of device.
    121 
    122   @param  This                   A pointer to EFI_DEVICE_IO protocol instance.
    123   @param  Width                  Width of I/O operations.
    124   @param  Address                The base address of I/O operations.
    125   @param  Count                  The number of I/O operations to perform.  Bytes
    126                                  moves is Width size * Count, starting at Address.
    127   @param  Buffer                 The source buffer of data to be written.
    128 
    129   @retval EFI_SUCCESS            The data was written to the device.
    130   @retval EFI_INVALID_PARAMETER  Width is invalid.
    131   @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to lack of
    132                                  resources.
    133 
    134 **/
    135 EFI_STATUS
    136 EFIAPI
    137 DeviceIoIoWrite (
    138   IN     EFI_DEVICE_IO_PROTOCOL    *This,
    139   IN     EFI_IO_WIDTH              Width,
    140   IN     UINT64                    Address,
    141   IN     UINTN                     Count,
    142   IN OUT VOID                      *Buffer
    143   );
    144 
    145 /**
    146   Perform reading PCI configuration space of device
    147 
    148   @param  This                   A pointer to EFI_DEVICE_IO protocol instance.
    149   @param  Width                  Width of I/O operations.
    150   @param  Address                The base address of I/O operations.
    151   @param  Count                  The number of I/O operations to perform.  Bytes
    152                                  moves is Width size * Count, starting at Address.
    153   @param  Buffer                 The destination buffer to store results.
    154 
    155   @retval EFI_SUCCESS            The data was read from the device.
    156   @retval EFI_INVALID_PARAMETER  Width is invalid.
    157   @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to lack of
    158                                  resources.
    159 
    160 **/
    161 EFI_STATUS
    162 EFIAPI
    163 DeviceIoPciRead (
    164   IN     EFI_DEVICE_IO_PROTOCOL   *This,
    165   IN     EFI_IO_WIDTH             Width,
    166   IN     UINT64                   Address,
    167   IN     UINTN                    Count,
    168   IN OUT VOID                     *Buffer
    169   );
    170 
    171 /**
    172   Perform writing PCI configuration space of device.
    173 
    174   @param  This                   A pointer to EFI_DEVICE_IO protocol instance.
    175   @param  Width                  Width of I/O operations.
    176   @param  Address                The base address of I/O operations.
    177   @param  Count                  The number of I/O operations to perform.  Bytes
    178                                  moves is Width size * Count, starting at Address.
    179   @param  Buffer                 The source buffer of data to be written.
    180 
    181   @retval EFI_SUCCESS            The data was written to the device.
    182   @retval EFI_INVALID_PARAMETER  Width is invalid.
    183   @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to lack of
    184                                  resources.
    185 
    186 **/
    187 EFI_STATUS
    188 EFIAPI
    189 DeviceIoPciWrite (
    190   IN     EFI_DEVICE_IO_PROTOCOL    *This,
    191   IN     EFI_IO_WIDTH              Width,
    192   IN     UINT64                    Address,
    193   IN     UINTN                     Count,
    194   IN OUT VOID                      *Buffer
    195   );
    196 
    197 /**
    198   Provides an EFI Device Path for a PCI device with the given PCI configuration space address.
    199 
    200   @param  This                   A pointer to the EFI_DEVICE_IO_INTERFACE instance.
    201   @param  Address                The PCI configuration space address of the device
    202                                  whose Device Path is going to be returned.
    203   @param  PciDevicePath          A pointer to the pointer for the EFI Device Path
    204                                  for PciAddress. Memory for the Device Path is
    205                                  allocated from the pool.
    206 
    207   @retval EFI_SUCCESS            The PciDevicePath returns a pointer to a valid EFI
    208                                  Device Path.
    209   @retval EFI_UNSUPPORTED        The PciAddress does not map to a valid EFI Device
    210                                  Path.
    211   @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a lack
    212                                  of resources.
    213 
    214 **/
    215 EFI_STATUS
    216 EFIAPI
    217 DeviceIoPciDevicePath (
    218   IN     EFI_DEVICE_IO_PROTOCOL        *This,
    219   IN     UINT64                        Address,
    220   IN OUT EFI_DEVICE_PATH_PROTOCOL      **PciDevicePath
    221   );
    222 
    223 /**
    224   Provides the device-specific addresses needed to access system memory.
    225 
    226   @param  This                   A pointer to the EFI_DEVICE_IO_INTERFACE instance.
    227   @param  Operation              Indicates if the bus master is going to read or
    228                                  write to system memory.
    229   @param  HostAddress            The system memory address to map to the device.
    230   @param  NumberOfBytes          On input the number of bytes to map. On output the
    231                                  number of bytes that were mapped.
    232   @param  DeviceAddress          The resulting map address for the bus master
    233                                  device to use to access the hosts HostAddress.
    234   @param  Mapping                A resulting value to pass to Unmap().
    235 
    236   @retval EFI_SUCCESS            The range was mapped for the returned
    237                                  NumberOfBytes.
    238   @retval EFI_INVALID_PARAMETER  The Operation or HostAddress is undefined.
    239   @retval EFI_UNSUPPORTED        The HostAddress cannot be mapped as a common
    240                                  buffer.
    241   @retval EFI_DEVICE_ERROR       The system hardware could not map the requested
    242                                  address.
    243   @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a lack
    244                                  of resources.
    245 
    246 **/
    247 EFI_STATUS
    248 EFIAPI
    249 DeviceIoMap (
    250   IN     EFI_DEVICE_IO_PROTOCOL   *This,
    251   IN     EFI_IO_OPERATION_TYPE    Operation,
    252   IN     EFI_PHYSICAL_ADDRESS     *HostAddress,
    253   IN OUT UINTN                    *NumberOfBytes,
    254   OUT    EFI_PHYSICAL_ADDRESS     *DeviceAddress,
    255   OUT    VOID                     **Mapping
    256   );
    257 
    258 /**
    259   Completes the Map() operation and releases any corresponding resources.
    260 
    261   @param  This                   A pointer to the EFI_DEVICE_IO_INTERFACE instance.
    262   @param  Mapping                The mapping value returned from Map().
    263 
    264   @retval EFI_SUCCESS            The range was unmapped.
    265   @retval EFI_DEVICE_ERROR       The data was not committed to the target system
    266                                  memory.
    267 
    268 **/
    269 EFI_STATUS
    270 EFIAPI
    271 DeviceIoUnmap (
    272   IN EFI_DEVICE_IO_PROTOCOL   *This,
    273   IN VOID                     *Mapping
    274   );
    275 
    276 /**
    277   Allocates pages that are suitable for an EFIBusMasterCommonBuffer mapping.
    278 
    279   @param  This                   A pointer to the EFI_DEVICE_IO_INTERFACE instance.
    280   @param  Type                   The type allocation to perform.
    281   @param  MemoryType             The type of memory to allocate,
    282                                  EfiBootServicesData or EfiRuntimeServicesData.
    283   @param  Pages                  The number of pages to allocate.
    284   @param  PhysicalAddress        A pointer to store the base address of the
    285                                  allocated range.
    286 
    287   @retval EFI_SUCCESS            The requested memory pages were allocated.
    288   @retval EFI_OUT_OF_RESOURCES   The memory pages could not be allocated.
    289   @retval EFI_INVALID_PARAMETER  The requested memory type is invalid.
    290   @retval EFI_UNSUPPORTED        The requested PhysicalAddress is not supported on
    291                                  this platform.
    292 
    293 **/
    294 EFI_STATUS
    295 EFIAPI
    296 DeviceIoAllocateBuffer (
    297   IN     EFI_DEVICE_IO_PROTOCOL    *This,
    298   IN     EFI_ALLOCATE_TYPE         Type,
    299   IN     EFI_MEMORY_TYPE           MemoryType,
    300   IN     UINTN                     Pages,
    301   IN OUT EFI_PHYSICAL_ADDRESS      *PhysicalAddress
    302   );
    303 
    304 /**
    305   Flushes any posted write data to the device.
    306 
    307   @param  This                   A pointer to the EFI_DEVICE_IO_INTERFACE instance.
    308 
    309   @retval EFI_SUCCESS            The buffers were flushed.
    310   @retval EFI_DEVICE_ERROR       The buffers were not flushed due to a hardware
    311                                  error.
    312 
    313 **/
    314 EFI_STATUS
    315 EFIAPI
    316 DeviceIoFlush (
    317   IN EFI_DEVICE_IO_PROTOCOL  *This
    318   );
    319 
    320 /**
    321   Frees pages that were allocated with AllocateBuffer().
    322 
    323   @param  This                   A pointer to the EFI_DEVICE_IO_INTERFACE instance.
    324   @param  Pages                  The number of pages to free.
    325   @param  HostAddress            The base address of the range to free.
    326 
    327   @retval EFI_SUCCESS            The requested memory pages were freed.
    328   @retval EFI_NOT_FOUND          The requested memory pages were not allocated with
    329                                  AllocateBuffer().
    330   @retval EFI_INVALID_PARAMETER  HostAddress is not page aligned or Pages is
    331                                  invalid.
    332 
    333 **/
    334 EFI_STATUS
    335 EFIAPI
    336 DeviceIoFreeBuffer (
    337   IN EFI_DEVICE_IO_PROTOCOL   *This,
    338   IN UINTN                    Pages,
    339   IN EFI_PHYSICAL_ADDRESS     HostAddress
    340   );
    341 
    342 
    343 #define DEVICE_IO_PRIVATE_DATA_SIGNATURE  SIGNATURE_32 ('D', 'e', 'I', 'O')
    344 
    345 typedef struct {
    346   UINTN                           Signature;
    347   EFI_DEVICE_IO_PROTOCOL          DeviceIo;
    348   EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
    349   EFI_DEVICE_PATH_PROTOCOL        *DevicePath;
    350   UINT16                          PrimaryBus;
    351   UINT16                          SubordinateBus;
    352 } DEVICE_IO_PRIVATE_DATA;
    353 
    354 #define DEVICE_IO_PRIVATE_DATA_FROM_THIS(a) CR (a, DEVICE_IO_PRIVATE_DATA, DeviceIo, DEVICE_IO_PRIVATE_DATA_SIGNATURE)
    355 
    356 #define MAX_COMMON_BUFFER                 0x00000000FFFFFFFF
    357 
    358 
    359 EFI_EVENT  mPciRootBridgeIoRegistration;
    360 
    361 //
    362 // Device Io Volume Protocol template
    363 //
    364 DEVICE_IO_PRIVATE_DATA gDeviceIoPrivateDataTemplate = {
    365   DEVICE_IO_PRIVATE_DATA_SIGNATURE,
    366   {
    367     {
    368       DeviceIoMemRead,
    369       DeviceIoMemWrite
    370     },
    371     {
    372       DeviceIoIoRead,
    373       DeviceIoIoWrite
    374     },
    375     {
    376       DeviceIoPciRead,
    377       DeviceIoPciWrite,
    378     },
    379     DeviceIoMap,
    380     DeviceIoPciDevicePath,
    381     DeviceIoUnmap,
    382     DeviceIoAllocateBuffer,
    383     DeviceIoFlush,
    384     DeviceIoFreeBuffer
    385   },
    386   NULL, // PciRootBridgeIo
    387   NULL, // DevicePath
    388   0,    // PrimaryBus
    389   255   // SubordinateBus
    390 };
    391 
    392 /**
    393   This notification function is invoked when an instance of the
    394   EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL is produced. It installs another instance of the
    395   EFI_DEVICE_IO_PROTOCOL on the same handle.
    396 
    397   @param  Event                 The event that occured
    398   @param  Context               Context of event. Not used in this nofication function.
    399 
    400 **/
    401 VOID
    402 EFIAPI
    403 PciRootBridgeIoNotificationEvent (
    404   IN  EFI_EVENT       Event,
    405   IN  VOID            *Context
    406   )
    407 {
    408   EFI_STATUS                     Status;
    409   UINTN                          BufferSize;
    410   EFI_HANDLE                     Handle;
    411   DEVICE_IO_PRIVATE_DATA         *Private;
    412   EFI_DEVICE_IO_PROTOCOL         *DeviceIo;
    413   EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
    414 
    415   while (TRUE) {
    416     BufferSize = sizeof (Handle);
    417     Status = gBS->LocateHandle (
    418                     ByRegisterNotify,
    419                     &gEfiPciRootBridgeIoProtocolGuid,
    420                     mPciRootBridgeIoRegistration,
    421                     &BufferSize,
    422                     &Handle
    423                     );
    424     if (EFI_ERROR (Status)) {
    425       //
    426       // Exit Path of While Loop....
    427       //
    428       break;
    429     }
    430 
    431     //
    432     // Skip this handle if the Device Io Protocol is already installed
    433     //
    434     Status = gBS->HandleProtocol (
    435                     Handle,
    436                     &gEfiDeviceIoProtocolGuid,
    437                     (VOID **)&DeviceIo
    438                     );
    439     if (!EFI_ERROR (Status)) {
    440       continue;
    441     }
    442 
    443     //
    444     // Retrieve the Pci Root Bridge IO Protocol
    445     //
    446     Status = gBS->HandleProtocol (
    447                     Handle,
    448                     &gEfiPciRootBridgeIoProtocolGuid,
    449                     (VOID **)&PciRootBridgeIo
    450                     );
    451     ASSERT_EFI_ERROR (Status);
    452 
    453     //
    454     // We only install Device IO for PCI bus in Segment 0.
    455     // See the file description at @file for details.
    456     //
    457     if (PciRootBridgeIo->SegmentNumber != 0) {
    458       continue;
    459     }
    460 
    461     //
    462     // Allocate private data structure
    463     //
    464     Private = AllocateCopyPool (sizeof (DEVICE_IO_PRIVATE_DATA), &gDeviceIoPrivateDataTemplate);
    465     if (Private == NULL) {
    466       continue;
    467     }
    468 
    469     Private->PciRootBridgeIo = PciRootBridgeIo;
    470 
    471     Status = gBS->HandleProtocol (
    472                     Handle,
    473                     &gEfiDevicePathProtocolGuid,
    474                     (VOID **) &Private->DevicePath
    475                     );
    476 
    477     //
    478     // Install Device Io onto same handle
    479     //
    480     Status = gBS->InstallMultipleProtocolInterfaces (
    481                     &Handle,
    482                     &gEfiDeviceIoProtocolGuid,
    483                     &Private->DeviceIo,
    484                     NULL
    485                     );
    486     ASSERT_EFI_ERROR (Status);
    487   }
    488 }
    489 
    490 /**
    491   The user Entry Point for DXE driver. The user code starts with this function
    492   as the real entry point for the image goes into a library that calls this
    493   function.
    494 
    495   @param[in] ImageHandle    The firmware allocated handle for the EFI image.
    496   @param[in] SystemTable    A pointer to the EFI System Table.
    497 
    498   @retval EFI_SUCCESS       The entry point is executed successfully.
    499   @retval other             Some error occurs when executing this entry point.
    500 
    501 **/
    502 EFI_STATUS
    503 EFIAPI
    504 InitializeDeviceIo (
    505   IN EFI_HANDLE        ImageHandle,
    506   IN EFI_SYSTEM_TABLE  *SystemTable
    507   )
    508 {
    509   EfiCreateProtocolNotifyEvent (
    510     &gEfiPciRootBridgeIoProtocolGuid,
    511     TPL_CALLBACK,
    512     PciRootBridgeIoNotificationEvent,
    513     NULL,
    514     &mPciRootBridgeIoRegistration
    515     );
    516   return EFI_SUCCESS;
    517 }
    518 
    519 
    520 /**
    521   Perform reading memory mapped I/O space of device.
    522 
    523   @param  This                   A pointer to EFI_DEVICE_IO protocol instance.
    524   @param  Width                  Width of I/O operations.
    525   @param  Address                The base address of I/O operations.
    526   @param  Count                  The number of I/O operations to perform.  Bytes
    527                                  moves is Width size * Count, starting at Address.
    528   @param  Buffer                 The destination buffer to store results.
    529 
    530   @retval EFI_SUCCESS            The data was read from the device.
    531   @retval EFI_INVALID_PARAMETER  Width is invalid.
    532   @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to lack of
    533                                  resources.
    534 
    535 **/
    536 EFI_STATUS
    537 EFIAPI
    538 DeviceIoMemRead (
    539   IN     EFI_DEVICE_IO_PROTOCOL   *This,
    540   IN     EFI_IO_WIDTH             Width,
    541   IN     UINT64                   Address,
    542   IN     UINTN                    Count,
    543   IN OUT VOID                     *Buffer
    544   )
    545 {
    546   EFI_STATUS              Status;
    547   DEVICE_IO_PRIVATE_DATA  *Private;
    548 
    549   Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
    550 
    551   if (Width > MMIO_COPY_UINT64) {
    552     return EFI_INVALID_PARAMETER;
    553   }
    554   if (Width >= MMIO_COPY_UINT8) {
    555     Width = (EFI_IO_WIDTH) (Width - MMIO_COPY_UINT8);
    556     Status = Private->PciRootBridgeIo->CopyMem (
    557                                          Private->PciRootBridgeIo,
    558                                          (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
    559                                          (UINT64) (UINTN) Buffer,
    560                                          Address,
    561                                          Count
    562                                          );
    563   } else {
    564     Status = Private->PciRootBridgeIo->Mem.Read (
    565                                              Private->PciRootBridgeIo,
    566                                              (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
    567                                              Address,
    568                                              Count,
    569                                              Buffer
    570                                              );
    571   }
    572 
    573   return Status;
    574 }
    575 
    576 
    577 
    578 
    579 /**
    580   Perform writing memory mapped I/O space of device.
    581 
    582   @param  This                   A pointer to EFI_DEVICE_IO protocol instance.
    583   @param  Width                  Width of I/O operations.
    584   @param  Address                The base address of I/O operations.
    585   @param  Count                  The number of I/O operations to perform.  Bytes
    586                                  moves is Width size * Count, starting at Address.
    587   @param  Buffer                 The source buffer of data to be written.
    588 
    589   @retval EFI_SUCCESS            The data was written to the device.
    590   @retval EFI_INVALID_PARAMETER  Width is invalid.
    591   @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to lack of
    592                                  resources.
    593 
    594 **/
    595 EFI_STATUS
    596 EFIAPI
    597 DeviceIoMemWrite (
    598   IN     EFI_DEVICE_IO_PROTOCOL    *This,
    599   IN     EFI_IO_WIDTH              Width,
    600   IN     UINT64                    Address,
    601   IN     UINTN                     Count,
    602   IN OUT VOID                      *Buffer
    603   )
    604 {
    605   EFI_STATUS              Status;
    606   DEVICE_IO_PRIVATE_DATA  *Private;
    607 
    608   Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
    609 
    610   if (Width > MMIO_COPY_UINT64) {
    611     return EFI_INVALID_PARAMETER;
    612   }
    613   if (Width >= MMIO_COPY_UINT8) {
    614     Width = (EFI_IO_WIDTH) (Width - MMIO_COPY_UINT8);
    615     Status = Private->PciRootBridgeIo->CopyMem (
    616                                          Private->PciRootBridgeIo,
    617                                          (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
    618                                          Address,
    619                                          (UINT64) (UINTN) Buffer,
    620                                          Count
    621                                          );
    622   } else {
    623     Status = Private->PciRootBridgeIo->Mem.Write (
    624                                              Private->PciRootBridgeIo,
    625                                              (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
    626                                              Address,
    627                                              Count,
    628                                              Buffer
    629                                              );
    630   }
    631 
    632   return Status;
    633 }
    634 
    635 
    636 /**
    637   Perform reading I/O space of device.
    638 
    639   @param  This                   A pointer to EFI_DEVICE_IO protocol instance.
    640   @param  Width                  Width of I/O operations.
    641   @param  Address                The base address of I/O operations.
    642   @param  Count                  The number of I/O operations to perform.  Bytes
    643                                  moves is Width size * Count, starting at Address.
    644   @param  Buffer                 The destination buffer to store results.
    645 
    646   @retval EFI_SUCCESS            The data was read from the device.
    647   @retval EFI_INVALID_PARAMETER  Width is invalid.
    648   @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to lack of
    649                                  resources.
    650 
    651 **/
    652 EFI_STATUS
    653 EFIAPI
    654 DeviceIoIoRead (
    655   IN     EFI_DEVICE_IO_PROTOCOL   *This,
    656   IN     EFI_IO_WIDTH             Width,
    657   IN     UINT64                   Address,
    658   IN     UINTN                    Count,
    659   IN OUT VOID                     *Buffer
    660   )
    661 {
    662   EFI_STATUS              Status;
    663   DEVICE_IO_PRIVATE_DATA  *Private;
    664 
    665   Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
    666 
    667   if (Width >= MMIO_COPY_UINT8) {
    668     return EFI_INVALID_PARAMETER;
    669   }
    670 
    671   Status = Private->PciRootBridgeIo->Io.Read (
    672                                           Private->PciRootBridgeIo,
    673                                           (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
    674                                           Address,
    675                                           Count,
    676                                           Buffer
    677                                           );
    678 
    679   return Status;
    680 }
    681 
    682 
    683 /**
    684   Perform writing I/O space of device.
    685 
    686   @param  This                   A pointer to EFI_DEVICE_IO protocol instance.
    687   @param  Width                  Width of I/O operations.
    688   @param  Address                The base address of I/O operations.
    689   @param  Count                  The number of I/O operations to perform.  Bytes
    690                                  moves is Width size * Count, starting at Address.
    691   @param  Buffer                 The source buffer of data to be written.
    692 
    693   @retval EFI_SUCCESS            The data was written to the device.
    694   @retval EFI_INVALID_PARAMETER  Width is invalid.
    695   @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to lack of
    696                                  resources.
    697 
    698 **/
    699 EFI_STATUS
    700 EFIAPI
    701 DeviceIoIoWrite (
    702   IN     EFI_DEVICE_IO_PROTOCOL    *This,
    703   IN     EFI_IO_WIDTH              Width,
    704   IN     UINT64                    Address,
    705   IN     UINTN                     Count,
    706   IN OUT VOID                      *Buffer
    707   )
    708 {
    709   EFI_STATUS              Status;
    710   DEVICE_IO_PRIVATE_DATA  *Private;
    711 
    712   Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
    713 
    714   if (Width >= MMIO_COPY_UINT8) {
    715     return EFI_INVALID_PARAMETER;
    716   }
    717 
    718   Status = Private->PciRootBridgeIo->Io.Write (
    719                                           Private->PciRootBridgeIo,
    720                                           (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
    721                                           Address,
    722                                           Count,
    723                                           Buffer
    724                                           );
    725 
    726   return Status;
    727 }
    728 
    729 
    730 /**
    731   Perform reading PCI configuration space of device
    732 
    733   @param  This                   A pointer to EFI_DEVICE_IO protocol instance.
    734   @param  Width                  Width of I/O operations.
    735   @param  Address                The base address of I/O operations.
    736   @param  Count                  The number of I/O operations to perform.  Bytes
    737                                  moves is Width size * Count, starting at Address.
    738   @param  Buffer                 The destination buffer to store results.
    739 
    740   @retval EFI_SUCCESS            The data was read from the device.
    741   @retval EFI_INVALID_PARAMETER  Width is invalid.
    742   @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to lack of
    743                                  resources.
    744 
    745 **/
    746 EFI_STATUS
    747 EFIAPI
    748 DeviceIoPciRead (
    749   IN     EFI_DEVICE_IO_PROTOCOL   *This,
    750   IN     EFI_IO_WIDTH             Width,
    751   IN     UINT64                   Address,
    752   IN     UINTN                    Count,
    753   IN OUT VOID                     *Buffer
    754   )
    755 {
    756   EFI_STATUS              Status;
    757   DEVICE_IO_PRIVATE_DATA  *Private;
    758 
    759   Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
    760 
    761   if ((UINT32)Width >= MMIO_COPY_UINT8) {
    762     return EFI_INVALID_PARAMETER;
    763   }
    764 
    765   Status = Private->PciRootBridgeIo->Pci.Read (
    766                                            Private->PciRootBridgeIo,
    767                                            (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
    768                                            Address,
    769                                            Count,
    770                                            Buffer
    771                                            );
    772 
    773   return Status;
    774 }
    775 
    776 
    777 /**
    778   Perform writing PCI configuration space of device.
    779 
    780   @param  This                   A pointer to EFI_DEVICE_IO protocol instance.
    781   @param  Width                  Width of I/O operations.
    782   @param  Address                The base address of I/O operations.
    783   @param  Count                  The number of I/O operations to perform.  Bytes
    784                                  moves is Width size * Count, starting at Address.
    785   @param  Buffer                 The source buffer of data to be written.
    786 
    787   @retval EFI_SUCCESS            The data was written to the device.
    788   @retval EFI_INVALID_PARAMETER  Width is invalid.
    789   @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to lack of
    790                                  resources.
    791 
    792 **/
    793 EFI_STATUS
    794 EFIAPI
    795 DeviceIoPciWrite (
    796   IN     EFI_DEVICE_IO_PROTOCOL    *This,
    797   IN     EFI_IO_WIDTH              Width,
    798   IN     UINT64                    Address,
    799   IN     UINTN                     Count,
    800   IN OUT VOID                      *Buffer
    801   )
    802 {
    803   EFI_STATUS              Status;
    804   DEVICE_IO_PRIVATE_DATA  *Private;
    805 
    806   Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
    807 
    808   if ((UINT32)Width >= MMIO_COPY_UINT8) {
    809     return EFI_INVALID_PARAMETER;
    810   }
    811 
    812   Status = Private->PciRootBridgeIo->Pci.Write (
    813                                            Private->PciRootBridgeIo,
    814                                            (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
    815                                            Address,
    816                                            Count,
    817                                            Buffer
    818                                            );
    819 
    820   return Status;
    821 }
    822 
    823 
    824 /**
    825   Append a PCI device path node to another device path.
    826 
    827   @param  Private                A pointer to DEVICE_IO_PRIVATE_DATA instance.
    828   @param  Bus                    PCI bus number of the device.
    829   @param  Device                 PCI device number of the device.
    830   @param  Function               PCI function number of the device.
    831   @param  DevicePath             Original device path which will be appended a PCI
    832                                  device path node.
    833   @param  BridgePrimaryBus       Primary bus number of the bridge.
    834   @param  BridgeSubordinateBus   Subordinate bus number of the bridge.
    835 
    836   @return Pointer to the appended PCI device path.
    837 
    838 **/
    839 EFI_DEVICE_PATH_PROTOCOL *
    840 AppendPciDevicePath (
    841   IN     DEVICE_IO_PRIVATE_DATA    *Private,
    842   IN     UINT8                     Bus,
    843   IN     UINT8                     Device,
    844   IN     UINT8                     Function,
    845   IN     EFI_DEVICE_PATH_PROTOCOL  *DevicePath,
    846   IN OUT UINT16                    *BridgePrimaryBus,
    847   IN OUT UINT16                    *BridgeSubordinateBus
    848   )
    849 {
    850   UINT16                    ThisBus;
    851   UINT8                     ThisDevice;
    852   UINT8                     ThisFunc;
    853   UINT64                    Address;
    854   PCI_TYPE01                PciBridge;
    855   PCI_TYPE01                *PciPtr;
    856   EFI_DEVICE_PATH_PROTOCOL  *ReturnDevicePath;
    857   PCI_DEVICE_PATH           PciNode;
    858 
    859   PciPtr = &PciBridge;
    860   for (ThisBus = *BridgePrimaryBus; ThisBus <= *BridgeSubordinateBus; ThisBus++) {
    861     for (ThisDevice = 0; ThisDevice <= PCI_MAX_DEVICE; ThisDevice++) {
    862       for (ThisFunc = 0; ThisFunc <= PCI_MAX_FUNC; ThisFunc++) {
    863         Address = EFI_PCI_ADDRESS (ThisBus, ThisDevice, ThisFunc, 0);
    864         ZeroMem (PciPtr, sizeof (PCI_TYPE01));
    865         Private->DeviceIo.Pci.Read (
    866                                 &Private->DeviceIo,
    867                                 IO_UINT32,
    868                                 Address,
    869                                 1,
    870                                 &(PciPtr->Hdr.VendorId)
    871                                 );
    872         if ((PciPtr->Hdr.VendorId == 0xffff) && (ThisFunc == 0)) {
    873           break;
    874         }
    875         if (PciPtr->Hdr.VendorId == 0xffff) {
    876           continue;
    877         } else {
    878           Private->DeviceIo.Pci.Read (
    879                                   &Private->DeviceIo,
    880                                   IO_UINT32,
    881                                   Address,
    882                                   sizeof (PCI_TYPE01) / sizeof (UINT32),
    883                                   PciPtr
    884                                   );
    885           if (IS_PCI_BRIDGE (PciPtr)) {
    886             if (Bus >= PciPtr->Bridge.SecondaryBus && Bus <= PciPtr->Bridge.SubordinateBus) {
    887 
    888               PciNode.Header.Type     = HARDWARE_DEVICE_PATH;
    889               PciNode.Header.SubType  = HW_PCI_DP;
    890               SetDevicePathNodeLength (&PciNode.Header, sizeof (PciNode));
    891 
    892               PciNode.Device        = ThisDevice;
    893               PciNode.Function      = ThisFunc;
    894               ReturnDevicePath      = AppendDevicePathNode (DevicePath, &PciNode.Header);
    895 
    896               *BridgePrimaryBus     = PciPtr->Bridge.SecondaryBus;
    897               *BridgeSubordinateBus = PciPtr->Bridge.SubordinateBus;
    898               return ReturnDevicePath;
    899             }
    900           }
    901           if (ThisFunc == 0 && ((PciPtr->Hdr.HeaderType & HEADER_TYPE_MULTI_FUNCTION) != HEADER_TYPE_MULTI_FUNCTION)) {
    902             //
    903             // Skip sub functions, this is not a multi function device
    904             //
    905             ThisFunc = 8;
    906           }
    907         }
    908       }
    909     }
    910   }
    911 
    912   ZeroMem (&PciNode, sizeof (PciNode));
    913   PciNode.Header.Type     = HARDWARE_DEVICE_PATH;
    914   PciNode.Header.SubType  = HW_PCI_DP;
    915   SetDevicePathNodeLength (&PciNode.Header, sizeof (PciNode));
    916   PciNode.Device        = Device;
    917   PciNode.Function      = Function;
    918 
    919   ReturnDevicePath      = AppendDevicePathNode (DevicePath, &PciNode.Header);
    920 
    921   *BridgePrimaryBus     = 0xffff;
    922   *BridgeSubordinateBus = 0xffff;
    923   return ReturnDevicePath;
    924 }
    925 
    926 
    927 /**
    928   Provides an EFI Device Path for a PCI device with the given PCI configuration space address.
    929 
    930   @param  This                   A pointer to the EFI_DEVICE_IO_INTERFACE instance.
    931   @param  Address                The PCI configuration space address of the device
    932                                  whose Device Path is going to be returned.
    933   @param  PciDevicePath          A pointer to the pointer for the EFI Device Path
    934                                  for PciAddress. Memory for the Device Path is
    935                                  allocated from the pool.
    936 
    937   @retval EFI_SUCCESS            The PciDevicePath returns a pointer to a valid EFI
    938                                  Device Path.
    939   @retval EFI_UNSUPPORTED        The PciAddress does not map to a valid EFI Device
    940                                  Path.
    941   @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a lack
    942                                  of resources.
    943 
    944 **/
    945 EFI_STATUS
    946 EFIAPI
    947 DeviceIoPciDevicePath (
    948   IN     EFI_DEVICE_IO_PROTOCOL        *This,
    949   IN     UINT64                        Address,
    950   IN OUT EFI_DEVICE_PATH_PROTOCOL      **PciDevicePath
    951   )
    952 {
    953   DEVICE_IO_PRIVATE_DATA  *Private;
    954   UINT16                  PrimaryBus;
    955   UINT16                  SubordinateBus;
    956   UINT8                   Bus;
    957   UINT8                   Device;
    958   UINT8                   Func;
    959 
    960   Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
    961 
    962   Bus     = (UINT8) (((UINT32) Address >> 24) & 0xff);
    963   Device  = (UINT8) (((UINT32) Address >> 16) & 0xff);
    964   Func    = (UINT8) (((UINT32) Address >> 8) & 0xff);
    965 
    966   if (Bus < Private->PrimaryBus || Bus > Private->SubordinateBus) {
    967     return EFI_UNSUPPORTED;
    968   }
    969 
    970   *PciDevicePath  = Private->DevicePath;
    971   PrimaryBus      = Private->PrimaryBus;
    972   SubordinateBus  = Private->SubordinateBus;
    973   do {
    974     *PciDevicePath = AppendPciDevicePath (
    975                        Private,
    976                        Bus,
    977                        Device,
    978                        Func,
    979                        *PciDevicePath,
    980                        &PrimaryBus,
    981                        &SubordinateBus
    982                        );
    983     if (*PciDevicePath == NULL) {
    984       return EFI_OUT_OF_RESOURCES;
    985     }
    986   } while (PrimaryBus != 0xffff);
    987 
    988   return EFI_SUCCESS;
    989 }
    990 
    991 
    992 /**
    993   Provides the device-specific addresses needed to access system memory.
    994 
    995   @param  This                   A pointer to the EFI_DEVICE_IO_INTERFACE instance.
    996   @param  Operation              Indicates if the bus master is going to read or
    997                                  write to system memory.
    998   @param  HostAddress            The system memory address to map to the device.
    999   @param  NumberOfBytes          On input the number of bytes to map. On output the
   1000                                  number of bytes that were mapped.
   1001   @param  DeviceAddress          The resulting map address for the bus master
   1002                                  device to use to access the hosts HostAddress.
   1003   @param  Mapping                A resulting value to pass to Unmap().
   1004 
   1005   @retval EFI_SUCCESS            The range was mapped for the returned
   1006                                  NumberOfBytes.
   1007   @retval EFI_INVALID_PARAMETER  The Operation or HostAddress is undefined.
   1008   @retval EFI_UNSUPPORTED        The HostAddress cannot be mapped as a common
   1009                                  buffer.
   1010   @retval EFI_DEVICE_ERROR       The system hardware could not map the requested
   1011                                  address.
   1012   @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a lack
   1013                                  of resources.
   1014 
   1015 **/
   1016 EFI_STATUS
   1017 EFIAPI
   1018 DeviceIoMap (
   1019   IN     EFI_DEVICE_IO_PROTOCOL   *This,
   1020   IN     EFI_IO_OPERATION_TYPE    Operation,
   1021   IN     EFI_PHYSICAL_ADDRESS     *HostAddress,
   1022   IN OUT UINTN                    *NumberOfBytes,
   1023   OUT    EFI_PHYSICAL_ADDRESS     *DeviceAddress,
   1024   OUT    VOID                     **Mapping
   1025   )
   1026 {
   1027   EFI_STATUS              Status;
   1028   DEVICE_IO_PRIVATE_DATA  *Private;
   1029 
   1030   Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
   1031 
   1032   if ((UINT32)Operation > EfiBusMasterCommonBuffer) {
   1033     return EFI_INVALID_PARAMETER;
   1034   }
   1035 
   1036   if (((UINTN) (*HostAddress) != (*HostAddress)) && Operation == EfiBusMasterCommonBuffer) {
   1037     return EFI_UNSUPPORTED;
   1038   }
   1039 
   1040   Status = Private->PciRootBridgeIo->Map (
   1041                                        Private->PciRootBridgeIo,
   1042                                        (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION) Operation,
   1043                                        (VOID *) (UINTN) (*HostAddress),
   1044                                        NumberOfBytes,
   1045                                        DeviceAddress,
   1046                                        Mapping
   1047                                        );
   1048 
   1049   return Status;
   1050 }
   1051 
   1052 
   1053 /**
   1054   Completes the Map() operation and releases any corresponding resources.
   1055 
   1056   @param  This                   A pointer to the EFI_DEVICE_IO_INTERFACE instance.
   1057   @param  Mapping                The mapping value returned from Map().
   1058 
   1059   @retval EFI_SUCCESS            The range was unmapped.
   1060   @retval EFI_DEVICE_ERROR       The data was not committed to the target system
   1061                                  memory.
   1062 
   1063 **/
   1064 EFI_STATUS
   1065 EFIAPI
   1066 DeviceIoUnmap (
   1067   IN EFI_DEVICE_IO_PROTOCOL   *This,
   1068   IN VOID                     *Mapping
   1069   )
   1070 {
   1071   EFI_STATUS              Status;
   1072   DEVICE_IO_PRIVATE_DATA  *Private;
   1073 
   1074   Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
   1075 
   1076   Status = Private->PciRootBridgeIo->Unmap (
   1077                                        Private->PciRootBridgeIo,
   1078                                        Mapping
   1079                                        );
   1080 
   1081   return Status;
   1082 }
   1083 
   1084 
   1085 /**
   1086   Allocates pages that are suitable for an EFIBusMasterCommonBuffer mapping.
   1087 
   1088   @param  This                   A pointer to the EFI_DEVICE_IO_INTERFACE instance.
   1089   @param  Type                   The type allocation to perform.
   1090   @param  MemoryType             The type of memory to allocate,
   1091                                  EfiBootServicesData or EfiRuntimeServicesData.
   1092   @param  Pages                  The number of pages to allocate.
   1093   @param  PhysicalAddress        A pointer to store the base address of the
   1094                                  allocated range.
   1095 
   1096   @retval EFI_SUCCESS            The requested memory pages were allocated.
   1097   @retval EFI_OUT_OF_RESOURCES   The memory pages could not be allocated.
   1098   @retval EFI_INVALID_PARAMETER  The requested memory type is invalid.
   1099   @retval EFI_UNSUPPORTED        The requested PhysicalAddress is not supported on
   1100                                  this platform.
   1101 
   1102 **/
   1103 EFI_STATUS
   1104 EFIAPI
   1105 DeviceIoAllocateBuffer (
   1106   IN     EFI_DEVICE_IO_PROTOCOL    *This,
   1107   IN     EFI_ALLOCATE_TYPE         Type,
   1108   IN     EFI_MEMORY_TYPE           MemoryType,
   1109   IN     UINTN                     Pages,
   1110   IN OUT EFI_PHYSICAL_ADDRESS      *PhysicalAddress
   1111   )
   1112 {
   1113   EFI_STATUS              Status;
   1114   EFI_PHYSICAL_ADDRESS    HostAddress;
   1115   DEVICE_IO_PRIVATE_DATA  *Private;
   1116   VOID                    *HostAddress2;
   1117 
   1118   Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
   1119 
   1120   HostAddress = *PhysicalAddress;
   1121 
   1122   if ((MemoryType != EfiBootServicesData) && (MemoryType != EfiRuntimeServicesData)) {
   1123     return EFI_INVALID_PARAMETER;
   1124   }
   1125 
   1126   if ((UINT32)Type >= MaxAllocateType) {
   1127     return EFI_INVALID_PARAMETER;
   1128   }
   1129 
   1130   if ((Type == AllocateAddress) && (HostAddress + EFI_PAGES_TO_SIZE (Pages) - 1 > MAX_COMMON_BUFFER)) {
   1131     return EFI_UNSUPPORTED;
   1132   }
   1133 
   1134   if ((AllocateAnyPages == Type) || (AllocateMaxAddress == Type && HostAddress > MAX_COMMON_BUFFER)) {
   1135     Type        = AllocateMaxAddress;
   1136     HostAddress = MAX_COMMON_BUFFER;
   1137   }
   1138 
   1139   HostAddress2 = (VOID *) (UINTN) (HostAddress);
   1140   Status = Private->PciRootBridgeIo->AllocateBuffer (
   1141                                        Private->PciRootBridgeIo,
   1142                                        Type,
   1143                                        MemoryType,
   1144                                        Pages,
   1145                                        &HostAddress2,
   1146                                        EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE |
   1147                                        EFI_PCI_ATTRIBUTE_MEMORY_CACHED
   1148                                        );
   1149 
   1150   if (EFI_ERROR (Status)) {
   1151     return Status;
   1152   }
   1153 
   1154 
   1155   *PhysicalAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress2;
   1156 
   1157   return EFI_SUCCESS;
   1158 }
   1159 
   1160 
   1161 /**
   1162   Flushes any posted write data to the device.
   1163 
   1164   @param  This                   A pointer to the EFI_DEVICE_IO_INTERFACE instance.
   1165 
   1166   @retval EFI_SUCCESS            The buffers were flushed.
   1167   @retval EFI_DEVICE_ERROR       The buffers were not flushed due to a hardware
   1168                                  error.
   1169 
   1170 **/
   1171 EFI_STATUS
   1172 EFIAPI
   1173 DeviceIoFlush (
   1174   IN EFI_DEVICE_IO_PROTOCOL  *This
   1175   )
   1176 {
   1177   EFI_STATUS              Status;
   1178   DEVICE_IO_PRIVATE_DATA  *Private;
   1179 
   1180   Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
   1181 
   1182   Status  = Private->PciRootBridgeIo->Flush (Private->PciRootBridgeIo);
   1183 
   1184   return Status;
   1185 }
   1186 
   1187 
   1188 /**
   1189   Frees pages that were allocated with AllocateBuffer().
   1190 
   1191   @param  This                   A pointer to the EFI_DEVICE_IO_INTERFACE instance.
   1192   @param  Pages                  The number of pages to free.
   1193   @param  HostAddress            The base address of the range to free.
   1194 
   1195   @retval EFI_SUCCESS            The requested memory pages were freed.
   1196   @retval EFI_NOT_FOUND          The requested memory pages were not allocated with
   1197                                  AllocateBuffer().
   1198   @retval EFI_INVALID_PARAMETER  HostAddress is not page aligned or Pages is
   1199                                  invalid.
   1200 
   1201 **/
   1202 EFI_STATUS
   1203 EFIAPI
   1204 DeviceIoFreeBuffer (
   1205   IN EFI_DEVICE_IO_PROTOCOL   *This,
   1206   IN UINTN                    Pages,
   1207   IN EFI_PHYSICAL_ADDRESS     HostAddress
   1208   )
   1209 {
   1210   DEVICE_IO_PRIVATE_DATA  *Private;
   1211 
   1212   Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
   1213 
   1214   if (((HostAddress & EFI_PAGE_MASK) != 0) || (Pages <= 0)) {
   1215     return EFI_INVALID_PARAMETER;
   1216   }
   1217 
   1218   return  Private->PciRootBridgeIo->FreeBuffer (
   1219             Private->PciRootBridgeIo,
   1220             Pages,
   1221             (VOID *) (UINTN) HostAddress
   1222             );
   1223 
   1224 }
   1225 
   1226