1 /** @file
2 
3   Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.<BR>
4   SPDX-License-Identifier: BSD-2-Clause-Patent
5 
6 **/
7 
8 #ifndef _EMMC_BLOCK_IO_PEI_H_
9 #define _EMMC_BLOCK_IO_PEI_H_
10 
11 #include <PiPei.h>
12 
13 #include <Ppi/SdMmcHostController.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/Emmc.h>
28 
29 typedef struct _EMMC_PEIM_HC_PRIVATE_DATA EMMC_PEIM_HC_PRIVATE_DATA;
30 typedef struct _EMMC_PEIM_HC_SLOT         EMMC_PEIM_HC_SLOT;
31 typedef struct _EMMC_TRB                  EMMC_TRB;
32 
33 #include "EmmcHci.h"
34 #include "EmmcHcMem.h"
35 
36 #define EMMC_PEIM_SIG               SIGNATURE_32 ('E', 'M', 'C', 'P')
37 #define EMMC_PEIM_SLOT_SIG          SIGNATURE_32 ('E', 'M', 'C', 'S')
38 
39 #define EMMC_PEIM_MAX_SLOTS         6
40 #define EMMC_PEIM_MAX_PARTITIONS    8
41 
42 struct _EMMC_PEIM_HC_SLOT {
43   UINT32                            Signature;
44   EFI_PEI_BLOCK_IO2_MEDIA           Media[EMMC_PEIM_MAX_PARTITIONS];
45   UINT8                             MediaNum;
46   EMMC_PARTITION_TYPE               PartitionType[EMMC_PEIM_MAX_PARTITIONS];
47 
48   UINTN                             EmmcHcBase;
49   EMMC_HC_SLOT_CAP                  Capability;
50   EMMC_CSD                          Csd;
51   EMMC_EXT_CSD                      ExtCsd;
52   BOOLEAN                           SectorAddressing;
53   EMMC_PEIM_HC_PRIVATE_DATA         *Private;
54 };
55 
56 struct _EMMC_PEIM_HC_PRIVATE_DATA {
57   UINT32                            Signature;
58   EMMC_PEIM_MEM_POOL                *Pool;
59   EFI_PEI_RECOVERY_BLOCK_IO_PPI     BlkIoPpi;
60   EFI_PEI_RECOVERY_BLOCK_IO2_PPI    BlkIo2Ppi;
61   EFI_PEI_PPI_DESCRIPTOR            BlkIoPpiList;
62   EFI_PEI_PPI_DESCRIPTOR            BlkIo2PpiList;
63 
64   //
65   // EndOfPei callback is used to do the cleanups before exit of PEI phase.
66   //
67   EFI_PEI_NOTIFY_DESCRIPTOR         EndOfPeiNotifyList;
68 
69   EMMC_PEIM_HC_SLOT                 Slot[EMMC_PEIM_MAX_SLOTS];
70   UINT8                             SlotNum;
71   UINT8                             TotalBlkIoDevices;
72 };
73 
74 #define EMMC_TIMEOUT                MultU64x32((UINT64)(3), 1000000)
75 #define GET_EMMC_PEIM_HC_PRIVATE_DATA_FROM_THIS(a) CR (a, EMMC_PEIM_HC_PRIVATE_DATA, BlkIoPpi, EMMC_PEIM_SIG)
76 #define GET_EMMC_PEIM_HC_PRIVATE_DATA_FROM_THIS2(a) CR (a, EMMC_PEIM_HC_PRIVATE_DATA, BlkIo2Ppi, EMMC_PEIM_SIG)
77 #define GET_EMMC_PEIM_HC_PRIVATE_DATA_FROM_THIS_NOTIFY(a) CR (a, EMMC_PEIM_HC_PRIVATE_DATA, EndOfPeiNotifyList, EMMC_PEIM_SIG)
78 
79 struct _EMMC_TRB {
80   EMMC_PEIM_HC_SLOT                   *Slot;
81   UINT16                              BlockSize;
82 
83   EMMC_COMMAND_PACKET                 *Packet;
84   VOID                                *Data;
85   UINT32                              DataLen;
86   BOOLEAN                             Read;
87   EFI_PHYSICAL_ADDRESS                DataPhy;
88   VOID                                *DataMap;
89   EMMC_HC_TRANSFER_MODE               Mode;
90 
91   UINT64                              Timeout;
92 
93   EMMC_HC_ADMA_DESC_LINE              *AdmaDesc;
94   UINTN                               AdmaDescSize;
95 };
96 
97 /**
98   Gets the count of block I/O devices that one specific block driver detects.
99 
100   This function is used for getting the count of block I/O devices that one
101   specific block driver detects.  To the PEI ATAPI driver, it returns the number
102   of all the detected ATAPI devices it detects during the enumeration process.
103   To the PEI legacy floppy driver, it returns the number of all the legacy
104   devices it finds during its enumeration process. If no device is detected,
105   then the function will return zero.
106 
107   @param[in]  PeiServices          General-purpose services that are available
108                                    to every PEIM.
109   @param[in]  This                 Indicates the EFI_PEI_RECOVERY_BLOCK_IO_PPI
110                                    instance.
111   @param[out] NumberBlockDevices   The number of block I/O devices discovered.
112 
113   @retval     EFI_SUCCESS          The operation performed successfully.
114 
115 **/
116 EFI_STATUS
117 EFIAPI
118 EmmcBlockIoPeimGetDeviceNo (
119   IN  EFI_PEI_SERVICES               **PeiServices,
120   IN  EFI_PEI_RECOVERY_BLOCK_IO_PPI  *This,
121   OUT UINTN                          *NumberBlockDevices
122   );
123 
124 /**
125   Gets a block device's media information.
126 
127   This function will provide the caller with the specified block device's media
128   information. If the media changes, calling this function will update the media
129   information accordingly.
130 
131   @param[in]  PeiServices   General-purpose services that are available to every
132                             PEIM
133   @param[in]  This          Indicates the EFI_PEI_RECOVERY_BLOCK_IO_PPI instance.
134   @param[in]  DeviceIndex   Specifies the block device to which the function wants
135                             to talk. Because the driver that implements Block I/O
136                             PPIs will manage multiple block devices, the PPIs that
137                             want to talk to a single device must specify the
138                             device index that was assigned during the enumeration
139                             process. This index is a number from one to
140                             NumberBlockDevices.
141   @param[out] MediaInfo     The media information of the specified block media.
142                             The caller is responsible for the ownership of this
143                             data structure.
144 
145   @par Note:
146       The MediaInfo structure describes an enumeration of possible block device
147       types.  This enumeration exists because no device paths are actually passed
148       across interfaces that describe the type or class of hardware that is publishing
149       the block I/O interface. This enumeration will allow for policy decisions
150       in the Recovery PEIM, such as "Try to recover from legacy floppy first,
151       LS-120 second, CD-ROM third." If there are multiple partitions abstracted
152       by a given device type, they should be reported in ascending order; this
153       order also applies to nested partitions, such as legacy MBR, where the
154       outermost partitions would have precedence in the reporting order. The
155       same logic applies to systems such as IDE that have precedence relationships
156       like "Master/Slave" or "Primary/Secondary". The master device should be
157       reported first, the slave second.
158 
159   @retval EFI_SUCCESS        Media information about the specified block device
160                              was obtained successfully.
161   @retval EFI_DEVICE_ERROR   Cannot get the media information due to a hardware
162                              error.
163 
164 **/
165 EFI_STATUS
166 EFIAPI
167 EmmcBlockIoPeimGetMediaInfo (
168   IN  EFI_PEI_SERVICES               **PeiServices,
169   IN  EFI_PEI_RECOVERY_BLOCK_IO_PPI  *This,
170   IN  UINTN                          DeviceIndex,
171   OUT EFI_PEI_BLOCK_IO_MEDIA         *MediaInfo
172   );
173 
174 /**
175   Reads the requested number of blocks from the specified block device.
176 
177   The function reads the requested number of blocks from the device. All the
178   blocks are read, or an error is returned. If there is no media in the device,
179   the function returns EFI_NO_MEDIA.
180 
181   @param[in]  PeiServices   General-purpose services that are available to
182                             every PEIM.
183   @param[in]  This          Indicates the EFI_PEI_RECOVERY_BLOCK_IO_PPI instance.
184   @param[in]  DeviceIndex   Specifies the block device to which the function wants
185                             to talk. Because the driver that implements Block I/O
186                             PPIs will manage multiple block devices, PPIs that
187                             want to talk to a single device must specify the device
188                             index that was assigned during the enumeration process.
189                             This index is a number from one to NumberBlockDevices.
190   @param[in]  StartLBA      The starting logical block address (LBA) to read from
191                             on the device
192   @param[in]  BufferSize    The size of the Buffer in bytes. This number must be
193                             a multiple of the intrinsic block size of the device.
194   @param[out] Buffer        A pointer to the destination buffer for the data.
195                             The caller is responsible for the ownership of the
196                             buffer.
197 
198   @retval EFI_SUCCESS             The data was read correctly from the device.
199   @retval EFI_DEVICE_ERROR        The device reported an error while attempting
200                                   to perform the read operation.
201   @retval EFI_INVALID_PARAMETER   The read request contains LBAs that are not
202                                   valid, or the buffer is not properly aligned.
203   @retval EFI_NO_MEDIA            There is no media in the device.
204   @retval EFI_BAD_BUFFER_SIZE     The BufferSize parameter is not a multiple of
205                                   the intrinsic block size of the device.
206 
207 **/
208 EFI_STATUS
209 EFIAPI
210 EmmcBlockIoPeimReadBlocks (
211   IN  EFI_PEI_SERVICES               **PeiServices,
212   IN  EFI_PEI_RECOVERY_BLOCK_IO_PPI  *This,
213   IN  UINTN                          DeviceIndex,
214   IN  EFI_PEI_LBA                    StartLBA,
215   IN  UINTN                          BufferSize,
216   OUT VOID                           *Buffer
217   );
218 
219 /**
220   Gets the count of block I/O devices that one specific block driver detects.
221 
222   This function is used for getting the count of block I/O devices that one
223   specific block driver detects.  To the PEI ATAPI driver, it returns the number
224   of all the detected ATAPI devices it detects during the enumeration process.
225   To the PEI legacy floppy driver, it returns the number of all the legacy
226   devices it finds during its enumeration process. If no device is detected,
227   then the function will return zero.
228 
229   @param[in]  PeiServices          General-purpose services that are available
230                                    to every PEIM.
231   @param[in]  This                 Indicates the EFI_PEI_RECOVERY_BLOCK_IO2_PPI
232                                    instance.
233   @param[out] NumberBlockDevices   The number of block I/O devices discovered.
234 
235   @retval     EFI_SUCCESS          The operation performed successfully.
236 
237 **/
238 EFI_STATUS
239 EFIAPI
240 EmmcBlockIoPeimGetDeviceNo2 (
241   IN  EFI_PEI_SERVICES               **PeiServices,
242   IN  EFI_PEI_RECOVERY_BLOCK_IO2_PPI *This,
243   OUT UINTN                          *NumberBlockDevices
244   );
245 
246 /**
247   Gets a block device's media information.
248 
249   This function will provide the caller with the specified block device's media
250   information. If the media changes, calling this function will update the media
251   information accordingly.
252 
253   @param[in]  PeiServices   General-purpose services that are available to every
254                             PEIM
255   @param[in]  This          Indicates the EFI_PEI_RECOVERY_BLOCK_IO2_PPI instance.
256   @param[in]  DeviceIndex   Specifies the block device to which the function wants
257                             to talk. Because the driver that implements Block I/O
258                             PPIs will manage multiple block devices, the PPIs that
259                             want to talk to a single device must specify the
260                             device index that was assigned during the enumeration
261                             process. This index is a number from one to
262                             NumberBlockDevices.
263   @param[out] MediaInfo     The media information of the specified block media.
264                             The caller is responsible for the ownership of this
265                             data structure.
266 
267   @par Note:
268       The MediaInfo structure describes an enumeration of possible block device
269       types.  This enumeration exists because no device paths are actually passed
270       across interfaces that describe the type or class of hardware that is publishing
271       the block I/O interface. This enumeration will allow for policy decisions
272       in the Recovery PEIM, such as "Try to recover from legacy floppy first,
273       LS-120 second, CD-ROM third." If there are multiple partitions abstracted
274       by a given device type, they should be reported in ascending order; this
275       order also applies to nested partitions, such as legacy MBR, where the
276       outermost partitions would have precedence in the reporting order. The
277       same logic applies to systems such as IDE that have precedence relationships
278       like "Master/Slave" or "Primary/Secondary". The master device should be
279       reported first, the slave second.
280 
281   @retval EFI_SUCCESS        Media information about the specified block device
282                              was obtained successfully.
283   @retval EFI_DEVICE_ERROR   Cannot get the media information due to a hardware
284                              error.
285 
286 **/
287 EFI_STATUS
288 EFIAPI
289 EmmcBlockIoPeimGetMediaInfo2 (
290   IN  EFI_PEI_SERVICES               **PeiServices,
291   IN  EFI_PEI_RECOVERY_BLOCK_IO2_PPI *This,
292   IN  UINTN                          DeviceIndex,
293   OUT EFI_PEI_BLOCK_IO2_MEDIA        *MediaInfo
294   );
295 
296 /**
297   Reads the requested number of blocks from the specified block device.
298 
299   The function reads the requested number of blocks from the device. All the
300   blocks are read, or an error is returned. If there is no media in the device,
301   the function returns EFI_NO_MEDIA.
302 
303   @param[in]  PeiServices   General-purpose services that are available to
304                             every PEIM.
305   @param[in]  This          Indicates the EFI_PEI_RECOVERY_BLOCK_IO2_PPI instance.
306   @param[in]  DeviceIndex   Specifies the block device to which the function wants
307                             to talk. Because the driver that implements Block I/O
308                             PPIs will manage multiple block devices, PPIs that
309                             want to talk to a single device must specify the device
310                             index that was assigned during the enumeration process.
311                             This index is a number from one to NumberBlockDevices.
312   @param[in]  StartLBA      The starting logical block address (LBA) to read from
313                             on the device
314   @param[in]  BufferSize    The size of the Buffer in bytes. This number must be
315                             a multiple of the intrinsic block size of the device.
316   @param[out] Buffer        A pointer to the destination buffer for the data.
317                             The caller is responsible for the ownership of the
318                             buffer.
319 
320   @retval EFI_SUCCESS             The data was read correctly from the device.
321   @retval EFI_DEVICE_ERROR        The device reported an error while attempting
322                                   to perform the read operation.
323   @retval EFI_INVALID_PARAMETER   The read request contains LBAs that are not
324                                   valid, or the buffer is not properly aligned.
325   @retval EFI_NO_MEDIA            There is no media in the device.
326   @retval EFI_BAD_BUFFER_SIZE     The BufferSize parameter is not a multiple of
327                                   the intrinsic block size of the device.
328 
329 **/
330 EFI_STATUS
331 EFIAPI
332 EmmcBlockIoPeimReadBlocks2 (
333   IN  EFI_PEI_SERVICES               **PeiServices,
334   IN  EFI_PEI_RECOVERY_BLOCK_IO2_PPI *This,
335   IN  UINTN                          DeviceIndex,
336   IN  EFI_PEI_LBA                    StartLBA,
337   IN  UINTN                          BufferSize,
338   OUT VOID                           *Buffer
339   );
340 
341 /**
342   Initialize the memory management pool for the host controller.
343 
344   @param  Private               The Emmc Peim driver private data.
345 
346   @retval EFI_SUCCESS           The memory pool is initialized.
347   @retval Others                Fail to init the memory pool.
348 
349 **/
350 EFI_STATUS
351 EmmcPeimInitMemPool (
352   IN  EMMC_PEIM_HC_PRIVATE_DATA      *Private
353   );
354 
355 /**
356   Release the memory management pool.
357 
358   @param  Pool                  The memory pool to free.
359 
360   @retval EFI_DEVICE_ERROR      Fail to free the memory pool.
361   @retval EFI_SUCCESS           The memory pool is freed.
362 
363 **/
364 EFI_STATUS
365 EmmcPeimFreeMemPool (
366   IN EMMC_PEIM_MEM_POOL       *Pool
367   );
368 
369 /**
370   Allocate some memory from the host controller's memory pool
371   which can be used to communicate with host controller.
372 
373   @param  Pool      The host controller's memory pool.
374   @param  Size      Size of the memory to allocate.
375 
376   @return The allocated memory or NULL.
377 
378 **/
379 VOID *
380 EmmcPeimAllocateMem (
381   IN  EMMC_PEIM_MEM_POOL        *Pool,
382   IN  UINTN                    Size
383   );
384 
385 /**
386   Free the allocated memory back to the memory pool.
387 
388   @param  Pool           The memory pool of the host controller.
389   @param  Mem            The memory to free.
390   @param  Size           The size of the memory to free.
391 
392 **/
393 VOID
394 EmmcPeimFreeMem (
395   IN EMMC_PEIM_MEM_POOL    *Pool,
396   IN VOID                 *Mem,
397   IN UINTN                Size
398   );
399 
400 /**
401   Initialize IOMMU.
402 **/
403 VOID
404 IoMmuInit (
405   VOID
406   );
407 
408 /**
409   Provides the controller-specific addresses required to access system memory from a
410   DMA bus master.
411 
412   @param  Operation             Indicates if the bus master is going to read or write to system memory.
413   @param  HostAddress           The system memory address to map to the PCI controller.
414   @param  NumberOfBytes         On input the number of bytes to map. On output the number of bytes
415                                 that were mapped.
416   @param  DeviceAddress         The resulting map address for the bus master PCI controller to use to
417                                 access the hosts HostAddress.
418   @param  Mapping               A resulting value to pass to Unmap().
419 
420   @retval EFI_SUCCESS           The range was mapped for the returned NumberOfBytes.
421   @retval EFI_UNSUPPORTED       The HostAddress cannot be mapped as a common buffer.
422   @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
423   @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.
424   @retval EFI_DEVICE_ERROR      The system hardware could not map the requested address.
425 
426 **/
427 EFI_STATUS
428 IoMmuMap (
429   IN  EDKII_IOMMU_OPERATION Operation,
430   IN  VOID                  *HostAddress,
431   IN  OUT UINTN             *NumberOfBytes,
432   OUT EFI_PHYSICAL_ADDRESS  *DeviceAddress,
433   OUT VOID                  **Mapping
434   );
435 
436 /**
437   Completes the Map() operation and releases any corresponding resources.
438 
439   @param  Mapping               The mapping value returned from Map().
440 
441   @retval EFI_SUCCESS           The range was unmapped.
442   @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned by Map().
443   @retval EFI_DEVICE_ERROR      The data was not committed to the target system memory.
444 **/
445 EFI_STATUS
446 IoMmuUnmap (
447   IN VOID                  *Mapping
448   );
449 
450 /**
451   Allocates pages that are suitable for an OperationBusMasterCommonBuffer or
452   OperationBusMasterCommonBuffer64 mapping.
453 
454   @param  Pages                 The number of pages to allocate.
455   @param  HostAddress           A pointer to store the base system memory address of the
456                                 allocated range.
457   @param  DeviceAddress         The resulting map address for the bus master PCI controller to use to
458                                 access the hosts HostAddress.
459   @param  Mapping               A resulting value to pass to Unmap().
460 
461   @retval EFI_SUCCESS           The requested memory pages were allocated.
462   @retval EFI_UNSUPPORTED       Attributes is unsupported. The only legal attribute bits are
463                                 MEMORY_WRITE_COMBINE and MEMORY_CACHED.
464   @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
465   @retval EFI_OUT_OF_RESOURCES  The memory pages could not be allocated.
466 
467 **/
468 EFI_STATUS
469 IoMmuAllocateBuffer (
470   IN UINTN                  Pages,
471   OUT VOID                  **HostAddress,
472   OUT EFI_PHYSICAL_ADDRESS  *DeviceAddress,
473   OUT VOID                  **Mapping
474   );
475 
476 /**
477   Frees memory that was allocated with AllocateBuffer().
478 
479   @param  Pages                 The number of pages to free.
480   @param  HostAddress           The base system memory address of the allocated range.
481   @param  Mapping               The mapping value returned from Map().
482 
483   @retval EFI_SUCCESS           The requested memory pages were freed.
484   @retval EFI_INVALID_PARAMETER The memory range specified by HostAddress and Pages
485                                 was not allocated with AllocateBuffer().
486 
487 **/
488 EFI_STATUS
489 IoMmuFreeBuffer (
490   IN UINTN                  Pages,
491   IN VOID                   *HostAddress,
492   IN VOID                   *Mapping
493   );
494 
495 /**
496   One notified function to cleanup the allocated DMA buffers at the end of PEI.
497 
498   @param[in]  PeiServices        Pointer to PEI Services Table.
499   @param[in]  NotifyDescriptor   Pointer to the descriptor for the Notification
500                                  event that caused this function to execute.
501   @param[in]  Ppi                Pointer to the PPI data associated with this function.
502 
503   @retval     EFI_SUCCESS  The function completes successfully
504 
505 **/
506 EFI_STATUS
507 EFIAPI
508 EmmcBlockIoPeimEndOfPei (
509   IN EFI_PEI_SERVICES           **PeiServices,
510   IN EFI_PEI_NOTIFY_DESCRIPTOR  *NotifyDescriptor,
511   IN VOID                       *Ppi
512   );
513 
514 #endif
515