1 /** @file
2 
3   Copyright (c) 2014 - 2018, Intel Corporation. All rights reserved.<BR>
4   SPDX-License-Identifier: BSD-2-Clause-Patent
5 
6 **/
7 
8 #ifndef _UFS_BLOCK_IO_PEI_H_
9 #define _UFS_BLOCK_IO_PEI_H_
10 
11 #include <PiPei.h>
12 
13 #include <Ppi/UfsHostController.h>
14 #include <Ppi/BlockIo.h>
15 #include <Ppi/BlockIo2.h>
16 #include <Ppi/IoMmu.h>
17 #include <Ppi/EndOfPeiPhase.h>
18 
19 #include <Library/DebugLib.h>
20 #include <Library/BaseLib.h>
21 #include <Library/BaseMemoryLib.h>
22 #include <Library/MemoryAllocationLib.h>
23 #include <Library/IoLib.h>
24 #include <Library/TimerLib.h>
25 #include <Library/PeiServicesLib.h>
26 
27 #include <IndustryStandard/Scsi.h>
28 
29 #include "UfsHci.h"
30 #include "UfsHcMem.h"
31 
32 #define UFS_PEIM_HC_SIG             SIGNATURE_32 ('U', 'F', 'S', 'H')
33 
34 #define UFS_PEIM_MAX_LUNS           8
35 
36 typedef struct {
37   UINT8    Lun[UFS_PEIM_MAX_LUNS];
38   UINT16   BitMask:12;              // Bit 0~7 is for common luns. Bit 8~11 is reserved for those well known luns
39   UINT16   Rsvd:4;
40 } UFS_PEIM_EXPOSED_LUNS;
41 
42 typedef struct {
43   ///
44   /// The timeout, in 100 ns units, to use for the execution of this SCSI
45   /// Request Packet. A Timeout value of 0 means that this function
46   /// will wait indefinitely for the SCSI Request Packet to execute. If
47   /// Timeout is greater than zero, then this function will return
48   /// EFI_TIMEOUT if the time required to execute the SCSI
49   /// Request Packet is greater than Timeout.
50   ///
51   UINT64 Timeout;
52   ///
53   /// A pointer to the data buffer to transfer between the SCSI
54   /// controller and the SCSI device for read and bidirectional commands.
55   ///
56   VOID   *InDataBuffer;
57   ///
58   /// A pointer to the data buffer to transfer between the SCSI
59   /// controller and the SCSI device for write or bidirectional commands.
60   ///
61   VOID   *OutDataBuffer;
62   ///
63   /// A pointer to the sense data that was generated by the execution of
64   /// the SCSI Request Packet.
65   ///
66   VOID   *SenseData;
67   ///
68   /// A pointer to buffer that contains the Command Data Block to
69   /// send to the SCSI device specified by Target and Lun.
70   ///
71   VOID   *Cdb;
72   ///
73   /// On Input, the size, in bytes, of InDataBuffer. On output, the
74   /// number of bytes transferred between the SCSI controller and the SCSI device.
75   ///
76   UINT32 InTransferLength;
77   ///
78   /// On Input, the size, in bytes of OutDataBuffer. On Output, the
79   /// Number of bytes transferred between SCSI Controller and the SCSI device.
80   ///
81   UINT32 OutTransferLength;
82   ///
83   /// The length, in bytes, of the buffer Cdb. The standard values are 6,
84   /// 10, 12, and 16, but other values are possible if a variable length CDB is used.
85   ///
86   UINT8  CdbLength;
87   ///
88   /// The direction of the data transfer. 0 for reads, 1 for writes. A
89   /// value of 2 is Reserved for Bi-Directional SCSI commands.
90   ///
91   UINT8  DataDirection;
92   ///
93   /// On input, the length in bytes of the SenseData buffer. On
94   /// output, the number of bytes written to the SenseData buffer.
95   ///
96   UINT8  SenseDataLength;
97 } UFS_SCSI_REQUEST_PACKET;
98 
99 typedef struct _UFS_PEIM_HC_PRIVATE_DATA {
100   UINT32                            Signature;
101   EFI_HANDLE                        Controller;
102 
103   UFS_PEIM_MEM_POOL                 *Pool;
104 
105   EFI_PEI_RECOVERY_BLOCK_IO_PPI     BlkIoPpi;
106   EFI_PEI_RECOVERY_BLOCK_IO2_PPI    BlkIo2Ppi;
107   EFI_PEI_PPI_DESCRIPTOR            BlkIoPpiList;
108   EFI_PEI_PPI_DESCRIPTOR            BlkIo2PpiList;
109   EFI_PEI_BLOCK_IO2_MEDIA           Media[UFS_PEIM_MAX_LUNS];
110 
111   //
112   // EndOfPei callback is used to stop the UFS DMA operation
113   // after exit PEI phase.
114   //
115   EFI_PEI_NOTIFY_DESCRIPTOR         EndOfPeiNotifyList;
116 
117   UINTN                             UfsHcBase;
118   UINT32                            Capabilities;
119 
120   UINT8                             TaskTag;
121 
122   VOID                              *UtpTrlBase;
123   UINT8                             Nutrs;
124   VOID                              *TrlMapping;
125   VOID                              *UtpTmrlBase;
126   UINT8                             Nutmrs;
127   VOID                              *TmrlMapping;
128 
129   UFS_PEIM_EXPOSED_LUNS             Luns;
130 } UFS_PEIM_HC_PRIVATE_DATA;
131 
132 #define UFS_TIMEOUT                 MultU64x32((UINT64)(3), 10000000)
133 
134 #define ROUNDUP8(x) (((x) % 8 == 0) ? (x) : ((x) / 8 + 1) * 8)
135 
136 #define IS_ALIGNED(addr, size)      (((UINTN) (addr) & (size - 1)) == 0)
137 
138 #define GET_UFS_PEIM_HC_PRIVATE_DATA_FROM_THIS(a) CR (a, UFS_PEIM_HC_PRIVATE_DATA, BlkIoPpi, UFS_PEIM_HC_SIG)
139 #define GET_UFS_PEIM_HC_PRIVATE_DATA_FROM_THIS2(a) CR (a, UFS_PEIM_HC_PRIVATE_DATA, BlkIo2Ppi, UFS_PEIM_HC_SIG)
140 #define GET_UFS_PEIM_HC_PRIVATE_DATA_FROM_THIS_NOTIFY(a) CR (a, UFS_PEIM_HC_PRIVATE_DATA, EndOfPeiNotifyList, UFS_PEIM_HC_SIG)
141 
142 #define UFS_SCSI_OP_LENGTH_SIX      0x6
143 #define UFS_SCSI_OP_LENGTH_TEN      0xa
144 #define UFS_SCSI_OP_LENGTH_SIXTEEN  0x10
145 
146 typedef struct _UFS_DEVICE_MANAGEMENT_REQUEST_PACKET {
147   UINT64                            Timeout;
148   VOID                              *InDataBuffer;
149   VOID                              *OutDataBuffer;
150   UINT8                             Opcode;
151   UINT8                             DescId;
152   UINT8                             Index;
153   UINT8                             Selector;
154   UINT32                            InTransferLength;
155   UINT32                            OutTransferLength;
156   UINT8                             DataDirection;
157   UINT8                             Ocs;
158 } UFS_DEVICE_MANAGEMENT_REQUEST_PACKET;
159 
160 /**
161   Sends a UFS-supported SCSI Request Packet to a UFS device that is attached to the UFS host controller.
162 
163   @param[in]      Private       The pointer to the UFS_PEIM_HC_PRIVATE_DATA data structure.
164   @param[in]      Lun           The LUN of the UFS device to send the SCSI Request Packet.
165   @param[in, out] Packet        A pointer to the SCSI Request Packet to send to a specified Lun of the
166                                 UFS device.
167 
168   @retval EFI_SUCCESS           The SCSI Request Packet was sent by the host. For bi-directional
169                                 commands, InTransferLength bytes were transferred from
170                                 InDataBuffer. For write and bi-directional commands,
171                                 OutTransferLength bytes were transferred by
172                                 OutDataBuffer.
173   @retval EFI_DEVICE_ERROR      A device error occurred while attempting to send the SCSI Request
174                                 Packet.
175   @retval EFI_OUT_OF_RESOURCES  The resource for transfer is not available.
176   @retval EFI_TIMEOUT           A timeout occurred while waiting for the SCSI Request Packet to execute.
177 
178 **/
179 EFI_STATUS
180 UfsExecScsiCmds (
181   IN     UFS_PEIM_HC_PRIVATE_DATA      *Private,
182   IN     UINT8                         Lun,
183   IN OUT UFS_SCSI_REQUEST_PACKET       *Packet
184   );
185 
186 /**
187   Initialize the UFS host controller.
188 
189   @param[in] Private                 The pointer to the UFS_PEIM_HC_PRIVATE_DATA data structure.
190 
191   @retval EFI_SUCCESS                The Ufs Host Controller is initialized successfully.
192   @retval Others                     A device error occurred while initializing the controller.
193 
194 **/
195 EFI_STATUS
196 UfsControllerInit (
197   IN  UFS_PEIM_HC_PRIVATE_DATA       *Private
198   );
199 
200 /**
201   Stop the UFS host controller.
202 
203   @param[in] Private                 The pointer to the UFS_PEIM_HC_PRIVATE_DATA data structure.
204 
205   @retval EFI_SUCCESS                The Ufs Host Controller is stopped successfully.
206   @retval Others                     A device error occurred while stopping the controller.
207 
208 **/
209 EFI_STATUS
210 UfsControllerStop (
211   IN  UFS_PEIM_HC_PRIVATE_DATA       *Private
212   );
213 
214 /**
215   Set specified flag to 1 on a UFS device.
216 
217   @param[in]  Private           The pointer to the UFS_PEIM_HC_PRIVATE_DATA data structure.
218   @param[in]  FlagId            The ID of flag to be set.
219 
220   @retval EFI_SUCCESS           The flag was set successfully.
221   @retval EFI_DEVICE_ERROR      A device error occurred while attempting to set the flag.
222   @retval EFI_TIMEOUT           A timeout occurred while waiting for the completion of setting the flag.
223 
224 **/
225 EFI_STATUS
226 UfsSetFlag (
227   IN  UFS_PEIM_HC_PRIVATE_DATA     *Private,
228   IN  UINT8                        FlagId
229   );
230 
231 /**
232   Read or write specified device descriptor of a UFS device.
233 
234   @param[in]      Private       The pointer to the UFS_PEIM_HC_PRIVATE_DATA data structure.
235   @param[in]      Read          The boolean variable to show r/w direction.
236   @param[in]      DescId        The ID of device descriptor.
237   @param[in]      Index         The Index of device descriptor.
238   @param[in]      Selector      The Selector of device descriptor.
239   @param[in, out] Descriptor    The buffer of device descriptor to be read or written.
240   @param[in]      DescSize      The size of device descriptor buffer.
241 
242   @retval EFI_SUCCESS           The device descriptor was read/written successfully.
243   @retval EFI_DEVICE_ERROR      A device error occurred while attempting to r/w the device descriptor.
244   @retval EFI_TIMEOUT           A timeout occurred while waiting for the completion of r/w the device descriptor.
245 
246 **/
247 EFI_STATUS
248 UfsRwDeviceDesc (
249   IN     UFS_PEIM_HC_PRIVATE_DATA     *Private,
250   IN     BOOLEAN                      Read,
251   IN     UINT8                        DescId,
252   IN     UINT8                        Index,
253   IN     UINT8                        Selector,
254   IN OUT VOID                         *Descriptor,
255   IN     UINT32                       DescSize
256   );
257 
258 /**
259   Sends NOP IN cmd to a UFS device for initialization process request.
260   For more details, please refer to UFS 2.0 spec Figure 13.3.
261 
262   @param[in]  Private           The pointer to the UFS_PEIM_HC_PRIVATE_DATA data structure.
263 
264   @retval EFI_SUCCESS           The NOP IN command was sent by the host. The NOP OUT response was
265                                 received successfully.
266   @retval EFI_DEVICE_ERROR      A device error occurred while attempting to execute NOP IN command.
267   @retval EFI_OUT_OF_RESOURCES  The resource for transfer is not available.
268   @retval EFI_TIMEOUT           A timeout occurred while waiting for the NOP IN command to execute.
269 
270 **/
271 EFI_STATUS
272 UfsExecNopCmds (
273   IN  UFS_PEIM_HC_PRIVATE_DATA       *Private
274   );
275 
276 /**
277   Gets the count of block I/O devices that one specific block driver detects.
278 
279   This function is used for getting the count of block I/O devices that one
280   specific block driver detects.  To the PEI ATAPI driver, it returns the number
281   of all the detected ATAPI devices it detects during the enumeration process.
282   To the PEI legacy floppy driver, it returns the number of all the legacy
283   devices it finds during its enumeration process. If no device is detected,
284   then the function will return zero.
285 
286   @param[in]  PeiServices          General-purpose services that are available
287                                    to every PEIM.
288   @param[in]  This                 Indicates the EFI_PEI_RECOVERY_BLOCK_IO_PPI
289                                    instance.
290   @param[out] NumberBlockDevices   The number of block I/O devices discovered.
291 
292   @retval     EFI_SUCCESS          The operation performed successfully.
293 
294 **/
295 EFI_STATUS
296 EFIAPI
297 UfsBlockIoPeimGetDeviceNo (
298   IN  EFI_PEI_SERVICES               **PeiServices,
299   IN  EFI_PEI_RECOVERY_BLOCK_IO_PPI  *This,
300   OUT UINTN                          *NumberBlockDevices
301   );
302 
303 /**
304   Gets a block device's media information.
305 
306   This function will provide the caller with the specified block device's media
307   information. If the media changes, calling this function will update the media
308   information accordingly.
309 
310   @param[in]  PeiServices   General-purpose services that are available to every
311                             PEIM
312   @param[in]  This          Indicates the EFI_PEI_RECOVERY_BLOCK_IO_PPI instance.
313   @param[in]  DeviceIndex   Specifies the block device to which the function wants
314                             to talk. Because the driver that implements Block I/O
315                             PPIs will manage multiple block devices, the PPIs that
316                             want to talk to a single device must specify the
317                             device index that was assigned during the enumeration
318                             process. This index is a number from one to
319                             NumberBlockDevices.
320   @param[out] MediaInfo     The media information of the specified block media.
321                             The caller is responsible for the ownership of this
322                             data structure.
323 
324   @par Note:
325       The MediaInfo structure describes an enumeration of possible block device
326       types.  This enumeration exists because no device paths are actually passed
327       across interfaces that describe the type or class of hardware that is publishing
328       the block I/O interface. This enumeration will allow for policy decisions
329       in the Recovery PEIM, such as "Try to recover from legacy floppy first,
330       LS-120 second, CD-ROM third." If there are multiple partitions abstracted
331       by a given device type, they should be reported in ascending order; this
332       order also applies to nested partitions, such as legacy MBR, where the
333       outermost partitions would have precedence in the reporting order. The
334       same logic applies to systems such as IDE that have precedence relationships
335       like "Master/Slave" or "Primary/Secondary". The master device should be
336       reported first, the slave second.
337 
338   @retval EFI_SUCCESS        Media information about the specified block device
339                              was obtained successfully.
340   @retval EFI_DEVICE_ERROR   Cannot get the media information due to a hardware
341                              error.
342 
343 **/
344 EFI_STATUS
345 EFIAPI
346 UfsBlockIoPeimGetMediaInfo (
347   IN  EFI_PEI_SERVICES               **PeiServices,
348   IN  EFI_PEI_RECOVERY_BLOCK_IO_PPI  *This,
349   IN  UINTN                          DeviceIndex,
350   OUT EFI_PEI_BLOCK_IO_MEDIA         *MediaInfo
351   );
352 
353 /**
354   Reads the requested number of blocks from the specified block device.
355 
356   The function reads the requested number of blocks from the device. All the
357   blocks are read, or an error is returned. If there is no media in the device,
358   the function returns EFI_NO_MEDIA.
359 
360   @param[in]  PeiServices   General-purpose services that are available to
361                             every PEIM.
362   @param[in]  This          Indicates the EFI_PEI_RECOVERY_BLOCK_IO_PPI instance.
363   @param[in]  DeviceIndex   Specifies the block device to which the function wants
364                             to talk. Because the driver that implements Block I/O
365                             PPIs will manage multiple block devices, PPIs that
366                             want to talk to a single device must specify the device
367                             index that was assigned during the enumeration process.
368                             This index is a number from one to NumberBlockDevices.
369   @param[in]  StartLBA      The starting logical block address (LBA) to read from
370                             on the device
371   @param[in]  BufferSize    The size of the Buffer in bytes. This number must be
372                             a multiple of the intrinsic block size of the device.
373   @param[out] Buffer        A pointer to the destination buffer for the data.
374                             The caller is responsible for the ownership of the
375                             buffer.
376 
377   @retval EFI_SUCCESS             The data was read correctly from the device.
378   @retval EFI_DEVICE_ERROR        The device reported an error while attempting
379                                   to perform the read operation.
380   @retval EFI_INVALID_PARAMETER   The read request contains LBAs that are not
381                                   valid, or the buffer is not properly aligned.
382   @retval EFI_NO_MEDIA            There is no media in the device.
383   @retval EFI_BAD_BUFFER_SIZE     The BufferSize parameter is not a multiple of
384                                   the intrinsic block size of the device.
385 
386 **/
387 EFI_STATUS
388 EFIAPI
389 UfsBlockIoPeimReadBlocks (
390   IN  EFI_PEI_SERVICES               **PeiServices,
391   IN  EFI_PEI_RECOVERY_BLOCK_IO_PPI  *This,
392   IN  UINTN                          DeviceIndex,
393   IN  EFI_PEI_LBA                    StartLBA,
394   IN  UINTN                          BufferSize,
395   OUT VOID                           *Buffer
396   );
397 
398 /**
399   Gets the count of block I/O devices that one specific block driver detects.
400 
401   This function is used for getting the count of block I/O devices that one
402   specific block driver detects.  To the PEI ATAPI driver, it returns the number
403   of all the detected ATAPI devices it detects during the enumeration process.
404   To the PEI legacy floppy driver, it returns the number of all the legacy
405   devices it finds during its enumeration process. If no device is detected,
406   then the function will return zero.
407 
408   @param[in]  PeiServices          General-purpose services that are available
409                                    to every PEIM.
410   @param[in]  This                 Indicates the EFI_PEI_RECOVERY_BLOCK_IO2_PPI
411                                    instance.
412   @param[out] NumberBlockDevices   The number of block I/O devices discovered.
413 
414   @retval     EFI_SUCCESS          The operation performed successfully.
415 
416 **/
417 EFI_STATUS
418 EFIAPI
419 UfsBlockIoPeimGetDeviceNo2 (
420   IN  EFI_PEI_SERVICES               **PeiServices,
421   IN  EFI_PEI_RECOVERY_BLOCK_IO2_PPI *This,
422   OUT UINTN                          *NumberBlockDevices
423   );
424 
425 /**
426   Gets a block device's media information.
427 
428   This function will provide the caller with the specified block device's media
429   information. If the media changes, calling this function will update the media
430   information accordingly.
431 
432   @param[in]  PeiServices   General-purpose services that are available to every
433                             PEIM
434   @param[in]  This          Indicates the EFI_PEI_RECOVERY_BLOCK_IO2_PPI instance.
435   @param[in]  DeviceIndex   Specifies the block device to which the function wants
436                             to talk. Because the driver that implements Block I/O
437                             PPIs will manage multiple block devices, the PPIs that
438                             want to talk to a single device must specify the
439                             device index that was assigned during the enumeration
440                             process. This index is a number from one to
441                             NumberBlockDevices.
442   @param[out] MediaInfo     The media information of the specified block media.
443                             The caller is responsible for the ownership of this
444                             data structure.
445 
446   @par Note:
447       The MediaInfo structure describes an enumeration of possible block device
448       types.  This enumeration exists because no device paths are actually passed
449       across interfaces that describe the type or class of hardware that is publishing
450       the block I/O interface. This enumeration will allow for policy decisions
451       in the Recovery PEIM, such as "Try to recover from legacy floppy first,
452       LS-120 second, CD-ROM third." If there are multiple partitions abstracted
453       by a given device type, they should be reported in ascending order; this
454       order also applies to nested partitions, such as legacy MBR, where the
455       outermost partitions would have precedence in the reporting order. The
456       same logic applies to systems such as IDE that have precedence relationships
457       like "Master/Slave" or "Primary/Secondary". The master device should be
458       reported first, the slave second.
459 
460   @retval EFI_SUCCESS        Media information about the specified block device
461                              was obtained successfully.
462   @retval EFI_DEVICE_ERROR   Cannot get the media information due to a hardware
463                              error.
464 
465 **/
466 EFI_STATUS
467 EFIAPI
468 UfsBlockIoPeimGetMediaInfo2 (
469   IN  EFI_PEI_SERVICES               **PeiServices,
470   IN  EFI_PEI_RECOVERY_BLOCK_IO2_PPI *This,
471   IN  UINTN                          DeviceIndex,
472   OUT EFI_PEI_BLOCK_IO2_MEDIA        *MediaInfo
473   );
474 
475 /**
476   Reads the requested number of blocks from the specified block device.
477 
478   The function reads the requested number of blocks from the device. All the
479   blocks are read, or an error is returned. If there is no media in the device,
480   the function returns EFI_NO_MEDIA.
481 
482   @param[in]  PeiServices   General-purpose services that are available to
483                             every PEIM.
484   @param[in]  This          Indicates the EFI_PEI_RECOVERY_BLOCK_IO2_PPI instance.
485   @param[in]  DeviceIndex   Specifies the block device to which the function wants
486                             to talk. Because the driver that implements Block I/O
487                             PPIs will manage multiple block devices, PPIs that
488                             want to talk to a single device must specify the device
489                             index that was assigned during the enumeration process.
490                             This index is a number from one to NumberBlockDevices.
491   @param[in]  StartLBA      The starting logical block address (LBA) to read from
492                             on the device
493   @param[in]  BufferSize    The size of the Buffer in bytes. This number must be
494                             a multiple of the intrinsic block size of the device.
495   @param[out] Buffer        A pointer to the destination buffer for the data.
496                             The caller is responsible for the ownership of the
497                             buffer.
498 
499   @retval EFI_SUCCESS             The data was read correctly from the device.
500   @retval EFI_DEVICE_ERROR        The device reported an error while attempting
501                                   to perform the read operation.
502   @retval EFI_INVALID_PARAMETER   The read request contains LBAs that are not
503                                   valid, or the buffer is not properly aligned.
504   @retval EFI_NO_MEDIA            There is no media in the device.
505   @retval EFI_BAD_BUFFER_SIZE     The BufferSize parameter is not a multiple of
506                                   the intrinsic block size of the device.
507 
508 **/
509 EFI_STATUS
510 EFIAPI
511 UfsBlockIoPeimReadBlocks2 (
512   IN  EFI_PEI_SERVICES               **PeiServices,
513   IN  EFI_PEI_RECOVERY_BLOCK_IO2_PPI *This,
514   IN  UINTN                          DeviceIndex,
515   IN  EFI_PEI_LBA                    StartLBA,
516   IN  UINTN                          BufferSize,
517   OUT VOID                           *Buffer
518   );
519 
520 /**
521   Initialize the memory management pool for the host controller.
522 
523   @param  Private               The Ufs Peim driver private data.
524 
525   @retval EFI_SUCCESS           The memory pool is initialized.
526   @retval Others                Fail to init the memory pool.
527 
528 **/
529 EFI_STATUS
530 UfsPeimInitMemPool (
531   IN  UFS_PEIM_HC_PRIVATE_DATA      *Private
532   );
533 
534 /**
535   Release the memory management pool.
536 
537   @param  Pool                  The memory pool to free.
538 
539   @retval EFI_DEVICE_ERROR      Fail to free the memory pool.
540   @retval EFI_SUCCESS           The memory pool is freed.
541 
542 **/
543 EFI_STATUS
544 UfsPeimFreeMemPool (
545   IN UFS_PEIM_MEM_POOL       *Pool
546   );
547 
548 /**
549   Allocate some memory from the host controller's memory pool
550   which can be used to communicate with host controller.
551 
552   @param  Pool      The host controller's memory pool.
553   @param  Size      Size of the memory to allocate.
554 
555   @return The allocated memory or NULL.
556 
557 **/
558 VOID *
559 UfsPeimAllocateMem (
560   IN  UFS_PEIM_MEM_POOL        *Pool,
561   IN  UINTN                    Size
562   );
563 
564 /**
565   Free the allocated memory back to the memory pool.
566 
567   @param  Pool           The memory pool of the host controller.
568   @param  Mem            The memory to free.
569   @param  Size           The size of the memory to free.
570 
571 **/
572 VOID
573 UfsPeimFreeMem (
574   IN UFS_PEIM_MEM_POOL    *Pool,
575   IN VOID                 *Mem,
576   IN UINTN                Size
577   );
578 
579 /**
580   Initialize IOMMU.
581 **/
582 VOID
583 IoMmuInit (
584   VOID
585   );
586 
587 /**
588   Provides the controller-specific addresses required to access system memory from a
589   DMA bus master.
590 
591   @param  Operation             Indicates if the bus master is going to read or write to system memory.
592   @param  HostAddress           The system memory address to map to the PCI controller.
593   @param  NumberOfBytes         On input the number of bytes to map. On output the number of bytes
594                                 that were mapped.
595   @param  DeviceAddress         The resulting map address for the bus master PCI controller to use to
596                                 access the hosts HostAddress.
597   @param  Mapping               A resulting value to pass to Unmap().
598 
599   @retval EFI_SUCCESS           The range was mapped for the returned NumberOfBytes.
600   @retval EFI_UNSUPPORTED       The HostAddress cannot be mapped as a common buffer.
601   @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
602   @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.
603   @retval EFI_DEVICE_ERROR      The system hardware could not map the requested address.
604 
605 **/
606 EFI_STATUS
607 IoMmuMap (
608   IN  EDKII_IOMMU_OPERATION Operation,
609   IN  VOID                  *HostAddress,
610   IN  OUT UINTN             *NumberOfBytes,
611   OUT EFI_PHYSICAL_ADDRESS  *DeviceAddress,
612   OUT VOID                  **Mapping
613   );
614 
615 /**
616   Completes the Map() operation and releases any corresponding resources.
617 
618   @param  Mapping               The mapping value returned from Map().
619 
620   @retval EFI_SUCCESS           The range was unmapped.
621   @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned by Map().
622   @retval EFI_DEVICE_ERROR      The data was not committed to the target system memory.
623 **/
624 EFI_STATUS
625 IoMmuUnmap (
626   IN VOID                  *Mapping
627   );
628 
629 /**
630   Allocates pages that are suitable for an OperationBusMasterCommonBuffer or
631   OperationBusMasterCommonBuffer64 mapping.
632 
633   @param  Pages                 The number of pages to allocate.
634   @param  HostAddress           A pointer to store the base system memory address of the
635                                 allocated range.
636   @param  DeviceAddress         The resulting map address for the bus master PCI controller to use to
637                                 access the hosts HostAddress.
638   @param  Mapping               A resulting value to pass to Unmap().
639 
640   @retval EFI_SUCCESS           The requested memory pages were allocated.
641   @retval EFI_UNSUPPORTED       Attributes is unsupported. The only legal attribute bits are
642                                 MEMORY_WRITE_COMBINE and MEMORY_CACHED.
643   @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
644   @retval EFI_OUT_OF_RESOURCES  The memory pages could not be allocated.
645 
646 **/
647 EFI_STATUS
648 IoMmuAllocateBuffer (
649   IN UINTN                  Pages,
650   OUT VOID                  **HostAddress,
651   OUT EFI_PHYSICAL_ADDRESS  *DeviceAddress,
652   OUT VOID                  **Mapping
653   );
654 
655 /**
656   Frees memory that was allocated with AllocateBuffer().
657 
658   @param  Pages                 The number of pages to free.
659   @param  HostAddress           The base system memory address of the allocated range.
660   @param  Mapping               The mapping value returned from Map().
661 
662   @retval EFI_SUCCESS           The requested memory pages were freed.
663   @retval EFI_INVALID_PARAMETER The memory range specified by HostAddress and Pages
664                                 was not allocated with AllocateBuffer().
665 
666 **/
667 EFI_STATUS
668 IoMmuFreeBuffer (
669   IN UINTN                  Pages,
670   IN VOID                   *HostAddress,
671   IN VOID                   *Mapping
672   );
673 
674 /**
675   One notified function to cleanup the allocated DMA buffers at the end of PEI.
676 
677   @param[in]  PeiServices        Pointer to PEI Services Table.
678   @param[in]  NotifyDescriptor   Pointer to the descriptor for the Notification
679                                  event that caused this function to execute.
680   @param[in]  Ppi                Pointer to the PPI data associated with this function.
681 
682   @retval     EFI_SUCCESS  The function completes successfully
683 
684 **/
685 EFI_STATUS
686 EFIAPI
687 UfsEndOfPei (
688   IN EFI_PEI_SERVICES           **PeiServices,
689   IN EFI_PEI_NOTIFY_DESCRIPTOR  *NotifyDescriptor,
690   IN VOID                       *Ppi
691   );
692 
693 #endif
694