• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
PciRootBridgeIoNotificationEvent(IN EFI_EVENT Event,IN VOID * Context)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
InitializeDeviceIo(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)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
DeviceIoMemRead(IN EFI_DEVICE_IO_PROTOCOL * This,IN EFI_IO_WIDTH Width,IN UINT64 Address,IN UINTN Count,IN OUT VOID * Buffer)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
DeviceIoMemWrite(IN EFI_DEVICE_IO_PROTOCOL * This,IN EFI_IO_WIDTH Width,IN UINT64 Address,IN UINTN Count,IN OUT VOID * Buffer)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
DeviceIoIoRead(IN EFI_DEVICE_IO_PROTOCOL * This,IN EFI_IO_WIDTH Width,IN UINT64 Address,IN UINTN Count,IN OUT VOID * Buffer)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
DeviceIoIoWrite(IN EFI_DEVICE_IO_PROTOCOL * This,IN EFI_IO_WIDTH Width,IN UINT64 Address,IN UINTN Count,IN OUT VOID * Buffer)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
DeviceIoPciRead(IN EFI_DEVICE_IO_PROTOCOL * This,IN EFI_IO_WIDTH Width,IN UINT64 Address,IN UINTN Count,IN OUT VOID * Buffer)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
DeviceIoPciWrite(IN EFI_DEVICE_IO_PROTOCOL * This,IN EFI_IO_WIDTH Width,IN UINT64 Address,IN UINTN Count,IN OUT VOID * Buffer)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 *
AppendPciDevicePath(IN DEVICE_IO_PRIVATE_DATA * Private,IN UINT8 Bus,IN UINT8 Device,IN UINT8 Function,IN EFI_DEVICE_PATH_PROTOCOL * DevicePath,IN OUT UINT16 * BridgePrimaryBus,IN OUT UINT16 * BridgeSubordinateBus)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
DeviceIoPciDevicePath(IN EFI_DEVICE_IO_PROTOCOL * This,IN UINT64 Address,IN OUT EFI_DEVICE_PATH_PROTOCOL ** PciDevicePath)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
DeviceIoMap(IN EFI_DEVICE_IO_PROTOCOL * This,IN EFI_IO_OPERATION_TYPE Operation,IN EFI_PHYSICAL_ADDRESS * HostAddress,IN OUT UINTN * NumberOfBytes,OUT EFI_PHYSICAL_ADDRESS * DeviceAddress,OUT VOID ** Mapping)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
DeviceIoUnmap(IN EFI_DEVICE_IO_PROTOCOL * This,IN VOID * Mapping)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
DeviceIoAllocateBuffer(IN EFI_DEVICE_IO_PROTOCOL * This,IN EFI_ALLOCATE_TYPE Type,IN EFI_MEMORY_TYPE MemoryType,IN UINTN Pages,IN OUT EFI_PHYSICAL_ADDRESS * PhysicalAddress)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
DeviceIoFlush(IN EFI_DEVICE_IO_PROTOCOL * This)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
DeviceIoFreeBuffer(IN EFI_DEVICE_IO_PROTOCOL * This,IN UINTN Pages,IN EFI_PHYSICAL_ADDRESS HostAddress)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