Revision: 17246
          http://sourceforge.net/p/edk2/code/17246
Author:   erictian
Date:     2015-04-29 02:42:58 +0000 (Wed, 29 Apr 2015)
Log Message:
-----------
MdeModulePkg: Add UFS (Universal Flash Storage) Stack

It includes 4 drivers:
1. UfsPassThruDxe, which is a UEFI driver and consumes 
EFI_UFS_HOST_CONTROLLER_PROTOCOL and produces EFI_EXT_SCSI_PASS_THRU_PROTOCOL
2. UfsPciHcDxe, which is specific for pci-based UFS HC implementation and is a 
UEFI driver to produce EFI_UFS_HOST_CONTROLLER_PROTOCOL.
3. UfsBlockIoPei, which is a PEI driver and consumes 
EFI_UFS_HOST_CONTROLLER_PPI and produces EFI_PEI_VIRTUAL_BLOCK_IO_PPI.
4. UfsPciHcPei, which is specific for pci-based UFS HC implementation and is a 
PEI driver to produce EFI_UFS_HOST_CONTROLLER_PPI.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Feng Tian <[email protected]>
Reviewed-by: Star Zeng <[email protected]>

Modified Paths:
--------------
    trunk/edk2/MdeModulePkg/MdeModulePkg.dec
    trunk/edk2/MdeModulePkg/MdeModulePkg.dsc
    trunk/edk2/MdeModulePkg/MdeModulePkg.uni

Added Paths:
-----------
    trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcDxe/
    trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcDxe/ComponentName.c
    trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcDxe/UfsPciHcDxe.c
    trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcDxe/UfsPciHcDxe.h
    trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcDxe/UfsPciHcDxe.inf
    trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcDxe/UfsPciHcDxe.uni
    trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcDxe/UfsPciHcDxeExtra.uni
    trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcPei/
    trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcPei/UfsPciHcPei.c
    trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcPei/UfsPciHcPei.h
    trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcPei/UfsPciHcPei.inf
    trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcPei/UfsPciHcPei.uni
    trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcPei/UfsPciHcPeiExtra.uni
    trunk/edk2/MdeModulePkg/Bus/Ufs/
    trunk/edk2/MdeModulePkg/Bus/Ufs/UfsBlockIoPei/
    trunk/edk2/MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsBlockIoPei.c
    trunk/edk2/MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsBlockIoPei.h
    trunk/edk2/MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsBlockIoPei.inf
    trunk/edk2/MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsBlockIoPei.uni
    trunk/edk2/MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsBlockIoPeiExtra.uni
    trunk/edk2/MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsHcMem.c
    trunk/edk2/MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsHcMem.h
    trunk/edk2/MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsHci.c
    trunk/edk2/MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsHci.h
    trunk/edk2/MdeModulePkg/Bus/Ufs/UfsPassThruDxe/
    trunk/edk2/MdeModulePkg/Bus/Ufs/UfsPassThruDxe/ComponentName.c
    trunk/edk2/MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThru.c
    trunk/edk2/MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThru.h
    trunk/edk2/MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThru.uni
    trunk/edk2/MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThruDxe.inf
    trunk/edk2/MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThruExtra.uni
    trunk/edk2/MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThruHci.c
    trunk/edk2/MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThruHci.h
    trunk/edk2/MdeModulePkg/Include/Ppi/UfsHostController.h
    trunk/edk2/MdeModulePkg/Include/Protocol/UfsHostController.h

Added: trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcDxe/ComponentName.c
===================================================================
--- trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcDxe/ComponentName.c                 
        (rev 0)
+++ trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcDxe/ComponentName.c 2015-04-29 
02:42:58 UTC (rev 17246)
@@ -0,0 +1,225 @@
+/** @file
+  UfsHcDxe driver produces EFI_UFS_HOST_CONTROLLER_PROTOCOL. The upper layer 
module
+  uses it to query the MMIO base address of the UFS host controller.
+
+  Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD 
License
+  which accompanies this distribution.  The full text of the license may be 
found at
+  http://opensource.org/licenses/bsd-license.php.
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "UfsPciHcDxe.h"
+
+//
+// EFI Component Name Protocol
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gUfsHcComponentName 
= {
+  UfsHcComponentNameGetDriverName,
+  UfsHcComponentNameGetControllerName,
+  "eng"
+};
+
+//
+// EFI Component Name 2 Protocol
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL 
gUfsHcComponentName2 = {
+  (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) UfsHcComponentNameGetDriverName,
+  (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) 
UfsHcComponentNameGetControllerName,
+  "en"
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mUfsHcDriverNameTable[] 
= {
+  {
+    "eng;en",
+    L"Universal Flash Storage (UFS) Pci Host Controller Driver"
+  },
+  { 
+    NULL,
+    NULL
+  }
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE 
mUfsHcControllerNameTable[] = {
+  {
+    "eng;en",
+    L"Universal Flash Storage (UFS) Pci Host Controller"
+  },
+  {
+    NULL,
+    NULL
+  }
+};
+
+/**
+  Retrieves a Unicode string that is the user readable name of the driver.
+
+  This function retrieves the user readable name of a driver in the form of a
+  Unicode string. If the driver specified by This has a user readable name in
+  the language specified by Language, then a pointer to the driver name is
+  returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
+  by This does not support the language specified by Language,
+  then EFI_UNSUPPORTED is returned.
+
+  @param  This[in]              A pointer to the EFI_COMPONENT_NAME2_PROTOCOL 
or
+                                EFI_COMPONENT_NAME_PROTOCOL instance.
+
+  @param  Language[in]          A pointer to a Null-terminated ASCII string
+                                array indicating the language. This is the
+                                language of the driver name that the caller is
+                                requesting, and it must match one of the
+                                languages specified in SupportedLanguages. The
+                                number of languages supported by a driver is up
+                                to the driver writer. Language is specified
+                                in RFC 4646 or ISO 639-2 language code format.
+
+  @param  DriverName[out]       A pointer to the Unicode string to return.
+                                This Unicode string is the name of the
+                                driver specified by This in the language
+                                specified by Language.
+
+  @retval EFI_SUCCESS           The Unicode string for the Driver specified by
+                                This and the language specified by Language was
+                                returned in DriverName.
+
+  @retval EFI_INVALID_PARAMETER Language is NULL.
+
+  @retval EFI_INVALID_PARAMETER DriverName is NULL.
+
+  @retval EFI_UNSUPPORTED       The driver specified by This does not support
+                                the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+UfsHcComponentNameGetDriverName (
+  IN  EFI_COMPONENT_NAME_PROTOCOL       *This,
+  IN  CHAR8                             *Language,
+  OUT CHAR16                            **DriverName
+  )
+{
+  return LookupUnicodeString2 (
+           Language,
+           This->SupportedLanguages,
+           mUfsHcDriverNameTable,
+           DriverName,
+           (BOOLEAN)(This == &gUfsHcComponentName)
+           );
+}
+
+/**
+  Retrieves a Unicode string that is the user readable name of the controller
+  that is being managed by a driver.
+
+  This function retrieves the user readable name of the controller specified by
+  ControllerHandle and ChildHandle in the form of a Unicode string. If the
+  driver specified by This has a user readable name in the language specified 
by
+  Language, then a pointer to the controller name is returned in 
ControllerName,
+  and EFI_SUCCESS is returned.  If the driver specified by This is not 
currently
+  managing the controller specified by ControllerHandle and ChildHandle,
+  then EFI_UNSUPPORTED is returned.  If the driver specified by This does not
+  support the language specified by Language, then EFI_UNSUPPORTED is returned.
+
+  @param  This[in]              A pointer to the EFI_COMPONENT_NAME2_PROTOCOL 
or
+                                EFI_COMPONENT_NAME_PROTOCOL instance.
+
+  @param  ControllerHandle[in]  The handle of a controller that the driver
+                                specified by This is managing.  This handle
+                                specifies the controller whose name is to be
+                                returned.
+
+  @param  ChildHandle[in]       The handle of the child controller to retrieve
+                                the name of.  This is an optional parameter 
that
+                                may be NULL.  It will be NULL for device
+                                drivers.  It will also be NULL for a bus 
drivers
+                                that wish to retrieve the name of the bus
+                                controller.  It will not be NULL for a bus
+                                driver that wishes to retrieve the name of a
+                                child controller.
+
+  @param  Language[in]          A pointer to a Null-terminated ASCII string
+                                array indicating the language.  This is the
+                                language of the driver name that the caller is
+                                requesting, and it must match one of the
+                                languages specified in SupportedLanguages. The
+                                number of languages supported by a driver is up
+                                to the driver writer. Language is specified in
+                                RFC 4646 or ISO 639-2 language code format.
+
+  @param  ControllerName[out]   A pointer to the Unicode string to return.
+                                This Unicode string is the name of the
+                                controller specified by ControllerHandle and
+                                ChildHandle in the language specified by
+                                Language from the point of view of the driver
+                                specified by This.
+
+  @retval EFI_SUCCESS           The Unicode string for the user readable name 
in
+                                the language specified by Language for the
+                                driver specified by This was returned in
+                                DriverName.
+
+  @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
+
+  @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
+                                EFI_HANDLE.
+
+  @retval EFI_INVALID_PARAMETER Language is NULL.
+
+  @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+
+  @retval EFI_UNSUPPORTED       The driver specified by This is not currently
+                                managing the controller specified by
+                                ControllerHandle and ChildHandle.
+
+  @retval EFI_UNSUPPORTED       The driver specified by This does not support
+                                the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+UfsHcComponentNameGetControllerName (
+  IN  EFI_COMPONENT_NAME_PROTOCOL                     *This,
+  IN  EFI_HANDLE                                      ControllerHandle,
+  IN  EFI_HANDLE                                      ChildHandle        
OPTIONAL,
+  IN  CHAR8                                           *Language,
+  OUT CHAR16                                          **ControllerName
+  )
+{
+  EFI_STATUS                    Status;
+
+  if (Language == NULL || ControllerName == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // This is a device driver, so ChildHandle must be NULL.
+  //
+  if (ChildHandle != NULL) {
+    return EFI_UNSUPPORTED;
+  }
+
+  //
+  // Make sure this driver is currently managing Controller Handle
+  //
+  Status = EfiTestManagedDevice (
+             ControllerHandle,
+             gUfsHcDriverBinding.DriverBindingHandle,
+             &gEfiPciIoProtocolGuid
+             );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  return LookupUnicodeString2 (
+           Language,
+           This->SupportedLanguages,
+           mUfsHcControllerNameTable,
+           ControllerName,
+           (BOOLEAN)(This == &gUfsHcComponentName)
+           );
+
+}

Added: trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcDxe/UfsPciHcDxe.c
===================================================================
--- trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcDxe/UfsPciHcDxe.c                   
        (rev 0)
+++ trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcDxe/UfsPciHcDxe.c   2015-04-29 
02:42:58 UTC (rev 17246)
@@ -0,0 +1,699 @@
+/** @file
+  UfsHcDxe driver is used to provide platform-dependent info, mainly UFS host 
controller
+  MMIO base, to upper layer UFS drivers.
+
+  Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD 
License
+  which accompanies this distribution.  The full text of the license may be 
found at
+  http://opensource.org/licenses/bsd-license.php.
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "UfsPciHcDxe.h"
+
+//
+// NVM Express Driver Binding Protocol Instance
+//
+EFI_DRIVER_BINDING_PROTOCOL gUfsHcDriverBinding = {
+  UfsHcDriverBindingSupported,
+  UfsHcDriverBindingStart,
+  UfsHcDriverBindingStop,
+  0x10,
+  NULL,
+  NULL
+};
+
+//
+// Template for Ufs host controller private data.
+//
+UFS_HOST_CONTROLLER_PRIVATE_DATA gUfsHcTemplate = {
+  UFS_HC_PRIVATE_DATA_SIGNATURE,  // Signature
+  NULL,                           // Handle
+  {                               // UfsHcProtocol
+    UfsHcGetMmioBar,
+    UfsHcAllocateBuffer,
+    UfsHcFreeBuffer,
+    UfsHcMap,
+    UfsHcUnmap,
+    UfsHcFlush
+  },
+  NULL,                           // PciIo
+  0                               // PciAttributes
+};
+
+/**
+  Get the MMIO base of the UFS host controller.
+
+  @param[in]   This             A pointer to the 
EFI_UFS_HOST_CONTROLLER_PROTOCOL instance.
+  @param[out]  MmioBar          The MMIO base address of UFS host controller.
+
+  @retval EFI_SUCCESS           The operation succeeds.
+  @retval others                The operation fails.
+**/
+EFI_STATUS
+EFIAPI
+UfsHcGetMmioBar (
+  IN     EDKII_UFS_HOST_CONTROLLER_PROTOCOL *This,
+     OUT UINTN                              *MmioBar
+  )
+{
+  UFS_HOST_CONTROLLER_PRIVATE_DATA  *Private;
+  EFI_PCI_IO_PROTOCOL               *PciIo;
+  EFI_STATUS                        Status;
+
+  if ((This == NULL) || (MmioBar == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Private = UFS_HOST_CONTROLLER_PRIVATE_DATA_FROM_UFSHC (This);
+  PciIo   = Private->PciIo;
+
+  Status = PciIo->Pci.Read (
+                        PciIo,
+                        EfiPciIoWidthUint8,
+                        PCI_BASE_ADDRESSREG_OFFSET,
+                        sizeof (UINT32),
+                        MmioBar
+                        );
+
+  if (!EFI_ERROR (Status)) {
+    *MmioBar &= (UINTN)~0xF;
+  }
+  return Status;
+}
+
+/**                                                                 
+  Provides the UFS controller-specific addresses needed to access system 
memory.
+            
+  @param  This                  A pointer to the 
EFI_UFS_HOST_CONTROLLER_PROTOCOL instance.
+  @param  Operation             Indicates if the bus master is going to read 
or write to system memory.
+  @param  HostAddress           The system memory address to map to the UFS 
controller.
+  @param  NumberOfBytes         On input the number of bytes to map. On output 
the number of bytes
+                                that were mapped.                              
                   
+  @param  DeviceAddress         The resulting map address for the bus master 
UFS controller to use to
+                                access the hosts HostAddress.                  
                      
+  @param  Mapping               A resulting value to pass to Unmap().
+                                  
+  @retval EFI_SUCCESS           The range was mapped for the returned 
NumberOfBytes.
+  @retval EFI_UNSUPPORTED       The HostAddress cannot be mapped as a common 
buffer.                                
+  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+  @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a 
lack of resources.
+  @retval EFI_DEVICE_ERROR      The system hardware could not map the 
requested address.
+                                   
+**/
+EFI_STATUS
+EFIAPI
+UfsHcMap (
+  IN     EDKII_UFS_HOST_CONTROLLER_PROTOCOL   *This,
+  IN     EDKII_UFS_HOST_CONTROLLER_OPERATION  Operation,
+  IN     VOID                                 *HostAddress,
+  IN OUT UINTN                                *NumberOfBytes,
+     OUT EFI_PHYSICAL_ADDRESS                 *DeviceAddress,
+     OUT VOID                                 **Mapping
+  )
+{
+  UFS_HOST_CONTROLLER_PRIVATE_DATA  *Private;
+  EFI_PCI_IO_PROTOCOL               *PciIo;
+  EFI_STATUS                        Status;
+
+  if ((This == NULL) || (HostAddress == NULL) || (NumberOfBytes == NULL) || 
(DeviceAddress == NULL) || (Mapping == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Private = UFS_HOST_CONTROLLER_PRIVATE_DATA_FROM_UFSHC (This);
+  PciIo   = Private->PciIo;
+
+  Status  = PciIo->Map (PciIo, Operation, HostAddress, NumberOfBytes, 
DeviceAddress, Mapping);
+  return Status;
+}
+
+/**                                                                 
+  Completes the Map() operation and releases any corresponding resources.
+            
+  @param  This                  A pointer to the 
EFI_UFS_HOST_CONTROLLER_PROTOCOL instance.                                      
+  @param  Mapping               The mapping value returned from Map().
+                                  
+  @retval EFI_SUCCESS           The range was unmapped.
+  @retval EFI_DEVICE_ERROR      The data was not committed to the target 
system memory.
+                                   
+**/
+EFI_STATUS
+EFIAPI
+UfsHcUnmap (
+  IN  EDKII_UFS_HOST_CONTROLLER_PROTOCOL *This,
+  IN  VOID                               *Mapping
+  )
+{
+  UFS_HOST_CONTROLLER_PRIVATE_DATA  *Private;
+  EFI_PCI_IO_PROTOCOL               *PciIo;
+  EFI_STATUS                        Status;
+
+  if ((This == NULL) || (Mapping == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Private = UFS_HOST_CONTROLLER_PRIVATE_DATA_FROM_UFSHC (This);
+  PciIo   = Private->PciIo;
+
+  Status  = PciIo->Unmap (PciIo, Mapping);
+  return Status;
+}
+
+/**                                                                 
+  Allocates pages that are suitable for an 
EfiUfsHcOperationBusMasterCommonBuffer
+  mapping.                                                                     
  
+            
+  @param  This                  A pointer to the 
EFI_UFS_HOST_CONTROLLER_PROTOCOL instance.
+  @param  Type                  This parameter is not used and must be ignored.
+  @param  MemoryType            The type of memory to allocate, 
EfiBootServicesData or
+                                EfiRuntimeServicesData.                        
       
+  @param  Pages                 The number of pages to allocate.               
                 
+  @param  HostAddress           A pointer to store the base system memory 
address of the
+                                allocated range.                               
         
+  @param  Attributes            The requested bit mask of attributes for the 
allocated range.
+                                  
+  @retval EFI_SUCCESS           The requested memory pages were allocated.
+  @retval EFI_UNSUPPORTED       Attributes is unsupported. The only legal 
attribute bits are
+                                MEMORY_WRITE_COMBINE and MEMORY_CACHED.        
             
+  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+  @retval EFI_OUT_OF_RESOURCES  The memory pages could not be allocated.  
+                                   
+**/
+EFI_STATUS
+EFIAPI
+UfsHcAllocateBuffer (
+  IN     EDKII_UFS_HOST_CONTROLLER_PROTOCOL *This,
+  IN     EFI_ALLOCATE_TYPE                  Type,
+  IN     EFI_MEMORY_TYPE                    MemoryType,
+  IN     UINTN                              Pages,
+     OUT VOID                               **HostAddress,
+  IN     UINT64                             Attributes
+  )
+{
+  UFS_HOST_CONTROLLER_PRIVATE_DATA  *Private;
+  EFI_PCI_IO_PROTOCOL               *PciIo;
+  EFI_STATUS                        Status;
+
+  if ((This == NULL) || (HostAddress == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Private = UFS_HOST_CONTROLLER_PRIVATE_DATA_FROM_UFSHC (This);
+  PciIo   = Private->PciIo;
+
+  Status  = PciIo->AllocateBuffer (PciIo, Type, MemoryType, Pages, 
HostAddress, Attributes);
+  return Status;
+}
+
+/**                                                                 
+  Frees memory that was allocated with AllocateBuffer().
+            
+  @param  This                  A pointer to the 
EFI_UFS_HOST_CONTROLLER_PROTOCOL instance.  
+  @param  Pages                 The number of pages to free.                   
             
+  @param  HostAddress           The base system memory address of the 
allocated range.                                    
+                                  
+  @retval EFI_SUCCESS           The requested memory pages were freed.
+  @retval EFI_INVALID_PARAMETER The memory range specified by HostAddress and 
Pages
+                                was not allocated with AllocateBuffer().
+                                     
+**/
+EFI_STATUS
+EFIAPI
+UfsHcFreeBuffer (
+  IN  EDKII_UFS_HOST_CONTROLLER_PROTOCOL *This,
+  IN  UINTN                              Pages,
+  IN  VOID                               *HostAddress
+  )
+{
+  UFS_HOST_CONTROLLER_PRIVATE_DATA  *Private;
+  EFI_PCI_IO_PROTOCOL               *PciIo;
+  EFI_STATUS                        Status;
+
+  if ((This == NULL) || (HostAddress == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Private = UFS_HOST_CONTROLLER_PRIVATE_DATA_FROM_UFSHC (This);
+  PciIo   = Private->PciIo;
+
+  Status  = PciIo->FreeBuffer (PciIo, Pages, HostAddress);
+  return Status;
+}
+
+/**                                                                 
+  Flushes all posted write transactions from the UFS bus to attached UFS 
device.
+            
+  @param  This                  A pointer to the 
EFI_UFS_HOST_CONTROLLER_PROTOCOL instance.  
+                                  
+  @retval EFI_SUCCESS           The posted write transactions were flushed 
from the UFS bus
+                                to attached UFS device.                        
              
+  @retval EFI_DEVICE_ERROR      The posted write transactions were not flushed 
from the UFS
+                                bus to attached UFS device due to a hardware 
error.                           
+                                     
+**/
+EFI_STATUS
+EFIAPI
+UfsHcFlush (
+  IN  EDKII_UFS_HOST_CONTROLLER_PROTOCOL *This
+  )
+{
+  UFS_HOST_CONTROLLER_PRIVATE_DATA  *Private;
+  EFI_PCI_IO_PROTOCOL               *PciIo;
+  EFI_STATUS                        Status;
+
+  Private = UFS_HOST_CONTROLLER_PRIVATE_DATA_FROM_UFSHC (This);
+  PciIo   = Private->PciIo;
+
+  Status  = PciIo->Flush (PciIo);
+  return Status;
+}
+
+/**
+  Tests to see if this driver supports a given controller. If a child device 
is provided,
+  it further tests to see if this driver supports creating a handle for the 
specified child device.
+
+  This function checks to see if the driver specified by This supports the 
device specified by
+  ControllerHandle. Drivers will typically use the device path attached to
+  ControllerHandle and/or the services from the bus I/O abstraction attached to
+  ControllerHandle to determine if the driver supports ControllerHandle. This 
function
+  may be called many times during platform initialization. In order to reduce 
boot times, the tests
+  performed by this function must be very small, and take as little time as 
possible to execute. This
+  function must not change the state of any hardware devices, and this 
function must be aware that the
+  device specified by ControllerHandle may already be managed by the same 
driver or a
+  different driver. This function must match its calls to AllocatePages() with 
FreePages(),
+  AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
+  Since ControllerHandle may have been previously started by the same driver, 
if a protocol is
+  already in the opened state, then it must not be closed with 
CloseProtocol(). This is required
+  to guarantee the state of ControllerHandle is not modified by this function.
+
+  @param[in]  This                 A pointer to the 
EFI_DRIVER_BINDING_PROTOCOL instance.
+  @param[in]  ControllerHandle     The handle of the controller to test. This 
handle
+                                   must support a protocol interface that 
supplies
+                                   an I/O abstraction to the driver.
+  @param[in]  RemainingDevicePath  A pointer to the remaining portion of a 
device path.  This
+                                   parameter is ignored by device drivers, and 
is optional for bus
+                                   drivers. For bus drivers, if this parameter 
is not NULL, then
+                                   the bus driver must determine if the bus 
controller specified
+                                   by ControllerHandle and the child 
controller specified
+                                   by RemainingDevicePath are both supported 
by this
+                                   bus driver.
+
+  @retval EFI_SUCCESS              The device specified by ControllerHandle and
+                                   RemainingDevicePath is supported by the 
driver specified by This.
+  @retval EFI_ALREADY_STARTED      The device specified by ControllerHandle and
+                                   RemainingDevicePath is already being 
managed by the driver
+                                   specified by This.
+  @retval EFI_ACCESS_DENIED        The device specified by ControllerHandle and
+                                   RemainingDevicePath is already being 
managed by a different
+                                   driver or an application that requires 
exclusive access.
+                                   Currently not implemented.
+  @retval EFI_UNSUPPORTED          The device specified by ControllerHandle and
+                                   RemainingDevicePath is not supported by the 
driver specified by This.
+**/
+EFI_STATUS
+EFIAPI
+UfsHcDriverBindingSupported (
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
+  IN EFI_HANDLE                   Controller,
+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
+  )
+{
+  EFI_STATUS                Status;
+  BOOLEAN                   UfsHcFound;
+  EFI_DEVICE_PATH_PROTOCOL  *ParentDevicePath;
+  EFI_PCI_IO_PROTOCOL       *PciIo;
+  PCI_TYPE00                PciData;
+
+  PciIo            = NULL;
+  ParentDevicePath = NULL;
+  UfsHcFound       = FALSE;
+
+  //
+  // UfsHcDxe is a device driver, and should ingore the
+  // "RemainingDevicePath" according to EFI spec
+  //
+  Status = gBS->OpenProtocol (
+                  Controller,
+                  &gEfiDevicePathProtocolGuid,
+                  (VOID *) &ParentDevicePath,
+                  This->DriverBindingHandle,
+                  Controller,
+                  EFI_OPEN_PROTOCOL_BY_DRIVER
+                  );
+  if (EFI_ERROR (Status)) {
+    //
+    // EFI_ALREADY_STARTED is also an error
+    //
+    return Status;
+  }
+  //
+  // Close the protocol because we don't use it here
+  //
+  gBS->CloseProtocol (
+        Controller,
+        &gEfiDevicePathProtocolGuid,
+        This->DriverBindingHandle,
+        Controller
+        );
+
+  //
+  // Now test the EfiPciIoProtocol
+  //
+  Status = gBS->OpenProtocol (
+                  Controller,
+                  &gEfiPciIoProtocolGuid,
+                  (VOID **) &PciIo,
+                  This->DriverBindingHandle,
+                  Controller,
+                  EFI_OPEN_PROTOCOL_BY_DRIVER
+                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+  //
+  // Now further check the PCI header: Base class (offset 0x0B) and
+  // Sub Class (offset 0x0A). This controller should be an UFS controller
+  //
+  Status = PciIo->Pci.Read (
+                        PciIo,
+                        EfiPciIoWidthUint8,
+                        0,
+                        sizeof (PciData),
+                        &PciData
+                        );
+  if (EFI_ERROR (Status)) {
+    gBS->CloseProtocol (
+          Controller,
+          &gEfiPciIoProtocolGuid,
+          This->DriverBindingHandle,
+          Controller
+          );
+    return EFI_UNSUPPORTED;
+  }
+  //
+  // Since we already got the PciData, we can close protocol to avoid to carry 
it on for multiple exit points.
+  //
+  gBS->CloseProtocol (
+        Controller,
+        &gEfiPciIoProtocolGuid,
+        This->DriverBindingHandle,
+        Controller
+        );
+
+  //
+  // Examine UFS Host Controller PCI Configuration table fields
+  //
+  if (PciData.Hdr.ClassCode[2] == PCI_CLASS_MASS_STORAGE) {
+    if (PciData.Hdr.ClassCode[1] == 0x09 ) { //UFS Controller Subclass
+      UfsHcFound = TRUE;
+    }
+  }
+
+  if (!UfsHcFound) {
+    return EFI_UNSUPPORTED;
+  }
+
+  return Status;
+}
+
+
+/**
+  Starts a device controller or a bus controller.
+
+  The Start() function is designed to be invoked from the EFI boot service 
ConnectController().
+  As a result, much of the error checking on the parameters to Start() has 
been moved into this
+  common boot service. It is legal to call Start() from other locations,
+  but the following calling restrictions must be followed or the system 
behavior will not be deterministic.
+  1. ControllerHandle must be a valid EFI_HANDLE.
+  2. If RemainingDevicePath is not NULL, then it must be a pointer to a 
naturally aligned
+     EFI_DEVICE_PATH_PROTOCOL.
+  3. Prior to calling Start(), the Supported() function for the driver 
specified by This must
+     have been called with the same calling parameters, and Supported() must 
have returned EFI_SUCCESS.
+
+  @param[in]  This                 A pointer to the 
EFI_DRIVER_BINDING_PROTOCOL instance.
+  @param[in]  ControllerHandle     The handle of the controller to start. This 
handle
+                                   must support a protocol interface that 
supplies
+                                   an I/O abstraction to the driver.
+  @param[in]  RemainingDevicePath  A pointer to the remaining portion of a 
device path.  This
+                                   parameter is ignored by device drivers, and 
is optional for bus
+                                   drivers. For a bus driver, if this 
parameter is NULL, then handles
+                                   for all the children of Controller are 
created by this driver.
+                                   If this parameter is not NULL and the first 
Device Path Node is
+                                   not the End of Device Path Node, then only 
the handle for the
+                                   child device specified by the first Device 
Path Node of
+                                   RemainingDevicePath is created by this 
driver.
+                                   If the first Device Path Node of 
RemainingDevicePath is
+                                   the End of Device Path Node, no child 
handle is created by this
+                                   driver.
+
+  @retval EFI_SUCCESS              The device was started.
+  @retval EFI_DEVICE_ERROR         The device could not be started due to a 
device error.Currently not implemented.
+  @retval EFI_OUT_OF_RESOURCES     The request could not be completed due to a 
lack of resources.
+  @retval Others                   The driver failded to start the device.
+
+**/
+EFI_STATUS
+EFIAPI
+UfsHcDriverBindingStart (
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
+  IN EFI_HANDLE                   Controller,
+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
+  )
+{
+  EFI_STATUS                        Status;
+  EFI_PCI_IO_PROTOCOL               *PciIo;
+  UFS_HOST_CONTROLLER_PRIVATE_DATA  *Private;
+  UINT64                            Supports;
+
+  PciIo    = NULL;
+  Private  = NULL;
+  Supports = 0;
+
+  //
+  // Now test and open the EfiPciIoProtocol
+  //
+  Status = gBS->OpenProtocol (
+                  Controller,
+                  &gEfiPciIoProtocolGuid,
+                  (VOID **) &PciIo,
+                  This->DriverBindingHandle,
+                  Controller,
+                  EFI_OPEN_PROTOCOL_BY_DRIVER
+                  );
+  //
+  // Status == 0 - A normal execution flow, SUCCESS and the program proceeds.
+  // Status == ALREADY_STARTED - A non-zero Status code returned. It indicates
+  //           that the protocol has been opened and should be treated as a
+  //           normal condition and the program proceeds. The Protocol will not
+  //           opened 'again' by this call.
+  // Status != ALREADY_STARTED - Error status, terminate program execution
+  //
+  if (EFI_ERROR (Status)) {
+    //
+    // EFI_ALREADY_STARTED is also an error
+    //
+    return Status;
+  }
+
+  Private = AllocateCopyPool (sizeof (UFS_HOST_CONTROLLER_PRIVATE_DATA), 
&gUfsHcTemplate);
+  if (Private == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto Done;
+  }
+
+  Private->PciIo = PciIo;
+
+  Status = PciIo->Attributes (
+                    PciIo,
+                    EfiPciIoAttributeOperationGet,
+                    0,
+                    &Private->PciAttributes
+                    );
+
+  if (EFI_ERROR (Status)) {
+    goto Done;
+  }
+
+  Status = PciIo->Attributes (
+                    PciIo,
+                    EfiPciIoAttributeOperationSupported,
+                    0,
+                    &Supports
+                    );
+
+  if (!EFI_ERROR (Status)) {
+    Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE;
+    Status    = PciIo->Attributes (
+                         PciIo,
+                         EfiPciIoAttributeOperationEnable,
+                         Supports,
+                         NULL
+                         );
+  } else {
+    goto Done;
+  }
+
+  ///
+  /// Install UFS_HOST_CONTROLLER protocol
+  ///
+  Status = gBS->InstallProtocolInterface (
+                  &Controller,
+                  &gEdkiiUfsHostControllerProtocolGuid,
+                  EFI_NATIVE_INTERFACE,
+                  (VOID*)&(Private->UfsHc)
+                  );
+
+Done:
+  if (EFI_ERROR (Status)) {
+    if ((Private != NULL) && (Private->PciAttributes != 0)) {
+      //
+      // Restore original PCI attributes
+      //
+      Status = PciIo->Attributes (
+                        PciIo,
+                        EfiPciIoAttributeOperationSet,
+                        Private->PciAttributes,
+                        NULL
+                        );
+      ASSERT_EFI_ERROR (Status);
+    }
+    gBS->CloseProtocol (
+          Controller,
+          &gEfiPciIoProtocolGuid,
+          This->DriverBindingHandle,
+          Controller
+          );
+    if (Private != NULL) {
+      FreePool (Private);
+    }
+  }
+
+  return Status;
+}
+
+
+/**
+  Stops a device controller or a bus controller.
+
+  The Stop() function is designed to be invoked from the EFI boot service 
DisconnectController().
+  As a result, much of the error checking on the parameters to Stop() has been 
moved
+  into this common boot service. It is legal to call Stop() from other 
locations,
+  but the following calling restrictions must be followed or the system 
behavior will not be deterministic.
+  1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous 
call to this
+     same driver's Start() function.
+  2. The first NumberOfChildren handles of ChildHandleBuffer must all be a 
valid
+     EFI_HANDLE. In addition, all of these handles must have been created in 
this driver's
+     Start() function, and the Start() function must have called 
OpenProtocol() on
+     ControllerHandle with an Attribute of 
EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
+
+  @param[in]  This              A pointer to the EFI_DRIVER_BINDING_PROTOCOL 
instance.
+  @param[in]  ControllerHandle  A handle to the device being stopped. The 
handle must
+                                support a bus specific I/O protocol for the 
driver
+                                to use to stop the device.
+  @param[in]  NumberOfChildren  The number of child device handles in 
ChildHandleBuffer.
+  @param[in]  ChildHandleBuffer An array of child handles to be freed. May be 
NULL
+                                if NumberOfChildren is 0.
+
+  @retval EFI_SUCCESS           The device was stopped.
+  @retval EFI_DEVICE_ERROR      The device could not be stopped due to a 
device error.
+
+**/
+EFI_STATUS
+EFIAPI
+UfsHcDriverBindingStop (
+  IN  EFI_DRIVER_BINDING_PROTOCOL     *This,
+  IN  EFI_HANDLE                      Controller,
+  IN  UINTN                           NumberOfChildren,
+  IN  EFI_HANDLE                      *ChildHandleBuffer
+  )
+{
+  EFI_STATUS                          Status;
+  UFS_HOST_CONTROLLER_PRIVATE_DATA    *Private;
+  EDKII_UFS_HOST_CONTROLLER_PROTOCOL  *UfsHc;
+
+  ///
+  /// Get private data
+  ///
+  Status = gBS->OpenProtocol (
+                  Controller,
+                  &gEdkiiUfsHostControllerProtocolGuid,
+                  (VOID **) &UfsHc,
+                  This->DriverBindingHandle,
+                  Controller,
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
+                  );
+
+  if (EFI_ERROR (Status)) {
+    return EFI_DEVICE_ERROR;
+  }
+
+  Private = UFS_HOST_CONTROLLER_PRIVATE_DATA_FROM_UFSHC (UfsHc);
+
+  Status = gBS->UninstallProtocolInterface (
+                  Controller,
+                  &gEdkiiUfsHostControllerProtocolGuid,
+                  &(Private->UfsHc)
+                  );
+  if (!EFI_ERROR (Status)) {
+    //
+    // Restore original PCI attributes
+    //
+    Status = Private->PciIo->Attributes (
+                               Private->PciIo,
+                               EfiPciIoAttributeOperationSet,
+                               Private->PciAttributes,
+                               NULL
+                               );
+    ASSERT_EFI_ERROR (Status);
+
+    //
+    // Close protocols opened by UFS host controller driver
+    //
+    gBS->CloseProtocol (
+           Controller,
+           &gEfiPciIoProtocolGuid,
+           This->DriverBindingHandle,
+           Controller
+           );
+
+    FreePool (Private);
+  }
+
+  return Status;
+}
+
+/**
+  The entry point for UFS host controller driver, used to install this driver 
on the ImageHandle.
+
+  @param[in]  ImageHandle   The firmware allocated handle for this driver 
image.
+  @param[in]  SystemTable   Pointer to the EFI system table.
+
+  @retval EFI_SUCCESS   Driver loaded.
+  @retval other         Driver not loaded.
+
+**/
+EFI_STATUS
+EFIAPI
+UfsHcDriverEntry (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  )
+{
+  EFI_STATUS           Status;
+
+  Status = EfiLibInstallDriverBindingComponentName2 (
+             ImageHandle,
+             SystemTable,
+             &gUfsHcDriverBinding,
+             ImageHandle,
+             &gUfsHcComponentName,
+             &gUfsHcComponentName2
+             );
+  ASSERT_EFI_ERROR (Status);
+
+  return Status;
+}

Added: trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcDxe/UfsPciHcDxe.h
===================================================================
--- trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcDxe/UfsPciHcDxe.h                   
        (rev 0)
+++ trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcDxe/UfsPciHcDxe.h   2015-04-29 
02:42:58 UTC (rev 17246)
@@ -0,0 +1,453 @@
+/** @file
+  UfsHcDxe driver is used to provide platform-dependent info, mainly UFS host 
controller
+  MMIO base, to upper layer UFS drivers.
+
+  Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD 
License
+  which accompanies this distribution.  The full text of the license may be 
found at
+  http://opensource.org/licenses/bsd-license.php.
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _EFI_UFS_HOST_CONTROLLER_H_
+#define _EFI_UFS_HOST_CONTROLLER_H_
+
+#include <Uefi.h>
+
+#include <IndustryStandard/Pci.h>
+
+#include <Protocol/ComponentName.h>
+#include <Protocol/ComponentName2.h>
+#include <Protocol/DriverBinding.h>
+#include <Protocol/LoadedImage.h>
+#include <Protocol/DevicePath.h>
+#include <Protocol/PciIo.h>
+#include <Protocol/UfsHostController.h>
+
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+
+extern EFI_DRIVER_BINDING_PROTOCOL                gUfsHcDriverBinding;
+extern EFI_COMPONENT_NAME_PROTOCOL                gUfsHcComponentName;
+extern EFI_COMPONENT_NAME2_PROTOCOL               gUfsHcComponentName2;
+
+//
+// Unique signature for private data structure.
+//
+#define UFS_HC_PRIVATE_DATA_SIGNATURE             SIGNATURE_32 
('U','F','S','H')
+
+typedef struct _UFS_HOST_CONTROLLER_PRIVATE_DATA  
UFS_HOST_CONTROLLER_PRIVATE_DATA;
+
+//
+// Nvme private data structure.
+//
+struct _UFS_HOST_CONTROLLER_PRIVATE_DATA {
+  UINT32                             Signature;
+  EFI_HANDLE                         Handle;
+
+  EDKII_UFS_HOST_CONTROLLER_PROTOCOL UfsHc;
+  EFI_PCI_IO_PROTOCOL                *PciIo;  
+  UINT64                             PciAttributes;
+};
+
+#define UFS_HOST_CONTROLLER_PRIVATE_DATA_FROM_UFSHC(a) \
+  CR (a, \
+      UFS_HOST_CONTROLLER_PRIVATE_DATA, \
+      UfsHc, \
+      UFS_HC_PRIVATE_DATA_SIGNATURE \
+      )
+
+/**
+  Retrieves a Unicode string that is the user readable name of the driver.
+
+  This function retrieves the user readable name of a driver in the form of a
+  Unicode string. If the driver specified by This has a user readable name in
+  the language specified by Language, then a pointer to the driver name is
+  returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
+  by This does not support the language specified by Language,
+  then EFI_UNSUPPORTED is returned.
+
+  @param  This[in]              A pointer to the EFI_COMPONENT_NAME2_PROTOCOL 
or
+                                EFI_COMPONENT_NAME_PROTOCOL instance.
+
+  @param  Language[in]          A pointer to a Null-terminated ASCII string
+                                array indicating the language. This is the
+                                language of the driver name that the caller is
+                                requesting, and it must match one of the
+                                languages specified in SupportedLanguages. The
+                                number of languages supported by a driver is up
+                                to the driver writer. Language is specified
+                                in RFC 4646 or ISO 639-2 language code format.
+
+  @param  DriverName[out]       A pointer to the Unicode string to return.
+                                This Unicode string is the name of the
+                                driver specified by This in the language
+                                specified by Language.
+
+  @retval EFI_SUCCESS           The Unicode string for the Driver specified by
+                                This and the language specified by Language was
+                                returned in DriverName.
+
+  @retval EFI_INVALID_PARAMETER Language is NULL.
+
+  @retval EFI_INVALID_PARAMETER DriverName is NULL.
+
+  @retval EFI_UNSUPPORTED       The driver specified by This does not support
+                                the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+UfsHcComponentNameGetDriverName (
+  IN  EFI_COMPONENT_NAME_PROTOCOL  *This,
+  IN  CHAR8                        *Language,
+  OUT CHAR16                       **DriverName
+  );
+
+/**
+  Retrieves a Unicode string that is the user readable name of the controller
+  that is being managed by a driver.
+
+  This function retrieves the user readable name of the controller specified by
+  ControllerHandle and ChildHandle in the form of a Unicode string. If the
+  driver specified by This has a user readable name in the language specified 
by
+  Language, then a pointer to the controller name is returned in 
ControllerName,
+  and EFI_SUCCESS is returned.  If the driver specified by This is not 
currently
+  managing the controller specified by ControllerHandle and ChildHandle,
+  then EFI_UNSUPPORTED is returned.  If the driver specified by This does not
+  support the language specified by Language, then EFI_UNSUPPORTED is returned.
+
+  @param  This[in]              A pointer to the EFI_COMPONENT_NAME2_PROTOCOL 
or
+                                EFI_COMPONENT_NAME_PROTOCOL instance.
+
+  @param  ControllerHandle[in]  The handle of a controller that the driver
+                                specified by This is managing.  This handle
+                                specifies the controller whose name is to be
+                                returned.
+
+  @param  ChildHandle[in]       The handle of the child controller to retrieve
+                                the name of.  This is an optional parameter 
that
+                                may be NULL.  It will be NULL for device
+                                drivers.  It will also be NULL for a bus 
drivers
+                                that wish to retrieve the name of the bus
+                                controller.  It will not be NULL for a bus
+                                driver that wishes to retrieve the name of a
+                                child controller.
+
+  @param  Language[in]          A pointer to a Null-terminated ASCII string
+                                array indicating the language.  This is the
+                                language of the driver name that the caller is
+                                requesting, and it must match one of the
+                                languages specified in SupportedLanguages. The
+                                number of languages supported by a driver is up
+                                to the driver writer. Language is specified in
+                                RFC 4646 or ISO 639-2 language code format.
+
+  @param  ControllerName[out]   A pointer to the Unicode string to return.
+                                This Unicode string is the name of the
+                                controller specified by ControllerHandle and
+                                ChildHandle in the language specified by
+                                Language from the point of view of the driver
+                                specified by This.
+
+  @retval EFI_SUCCESS           The Unicode string for the user readable name 
in
+                                the language specified by Language for the
+                                driver specified by This was returned in
+                                DriverName.
+
+  @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
+
+  @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
+                                EFI_HANDLE.
+
+  @retval EFI_INVALID_PARAMETER Language is NULL.
+
+  @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+
+  @retval EFI_UNSUPPORTED       The driver specified by This is not currently
+                                managing the controller specified by
+                                ControllerHandle and ChildHandle.
+
+  @retval EFI_UNSUPPORTED       The driver specified by This does not support
+                                the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+UfsHcComponentNameGetControllerName (
+  IN  EFI_COMPONENT_NAME_PROTOCOL                     *This,
+  IN  EFI_HANDLE                                      ControllerHandle,
+  IN  EFI_HANDLE                                      ChildHandle        
OPTIONAL,
+  IN  CHAR8                                           *Language,
+  OUT CHAR16                                          **ControllerName
+  );
+
+/**
+  Tests to see if this driver supports a given controller. If a child device 
is provided,
+  it further tests to see if this driver supports creating a handle for the 
specified child device.
+
+  This function checks to see if the driver specified by This supports the 
device specified by
+  ControllerHandle. Drivers will typically use the device path attached to
+  ControllerHandle and/or the services from the bus I/O abstraction attached to
+  ControllerHandle to determine if the driver supports ControllerHandle. This 
function
+  may be called many times during platform initialization. In order to reduce 
boot times, the tests
+  performed by this function must be very small, and take as little time as 
possible to execute. This
+  function must not change the state of any hardware devices, and this 
function must be aware that the
+  device specified by ControllerHandle may already be managed by the same 
driver or a
+  different driver. This function must match its calls to AllocatePages() with 
FreePages(),
+  AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
+  Since ControllerHandle may have been previously started by the same driver, 
if a protocol is
+  already in the opened state, then it must not be closed with 
CloseProtocol(). This is required
+  to guarantee the state of ControllerHandle is not modified by this function.
+
+  @param[in]  This                 A pointer to the 
EFI_DRIVER_BINDING_PROTOCOL instance.
+  @param[in]  ControllerHandle     The handle of the controller to test. This 
handle
+                                   must support a protocol interface that 
supplies
+                                   an I/O abstraction to the driver.
+  @param[in]  RemainingDevicePath  A pointer to the remaining portion of a 
device path.  This
+                                   parameter is ignored by device drivers, and 
is optional for bus
+                                   drivers. For bus drivers, if this parameter 
is not NULL, then
+                                   the bus driver must determine if the bus 
controller specified
+                                   by ControllerHandle and the child 
controller specified
+                                   by RemainingDevicePath are both supported 
by this
+                                   bus driver.
+
+  @retval EFI_SUCCESS              The device specified by ControllerHandle and
+                                   RemainingDevicePath is supported by the 
driver specified by This.
+  @retval EFI_ALREADY_STARTED      The device specified by ControllerHandle and
+                                   RemainingDevicePath is already being 
managed by the driver
+                                   specified by This.
+  @retval EFI_ACCESS_DENIED        The device specified by ControllerHandle and
+                                   RemainingDevicePath is already being 
managed by a different
+                                   driver or an application that requires 
exclusive access.
+                                   Currently not implemented.
+  @retval EFI_UNSUPPORTED          The device specified by ControllerHandle and
+                                   RemainingDevicePath is not supported by the 
driver specified by This.
+**/
+EFI_STATUS
+EFIAPI
+UfsHcDriverBindingSupported (
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
+  IN EFI_HANDLE                   Controller,
+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
+  );
+
+/**
+  Starts a device controller or a bus controller.
+
+  The Start() function is designed to be invoked from the EFI boot service 
ConnectController().
+  As a result, much of the error checking on the parameters to Start() has 
been moved into this
+  common boot service. It is legal to call Start() from other locations,
+  but the following calling restrictions must be followed or the system 
behavior will not be deterministic.
+  1. ControllerHandle must be a valid EFI_HANDLE.
+  2. If RemainingDevicePath is not NULL, then it must be a pointer to a 
naturally aligned
+     EFI_DEVICE_PATH_PROTOCOL.
+  3. Prior to calling Start(), the Supported() function for the driver 
specified by This must
+     have been called with the same calling parameters, and Supported() must 
have returned EFI_SUCCESS.
+
+  @param[in]  This                 A pointer to the 
EFI_DRIVER_BINDING_PROTOCOL instance.
+  @param[in]  ControllerHandle     The handle of the controller to start. This 
handle
+                                   must support a protocol interface that 
supplies
+                                   an I/O abstraction to the driver.
+  @param[in]  RemainingDevicePath  A pointer to the remaining portion of a 
device path.  This
+                                   parameter is ignored by device drivers, and 
is optional for bus
+                                   drivers. For a bus driver, if this 
parameter is NULL, then handles
+                                   for all the children of Controller are 
created by this driver.
+                                   If this parameter is not NULL and the first 
Device Path Node is
+                                   not the End of Device Path Node, then only 
the handle for the
+                                   child device specified by the first Device 
Path Node of
+                                   RemainingDevicePath is created by this 
driver.
+                                   If the first Device Path Node of 
RemainingDevicePath is
+                                   the End of Device Path Node, no child 
handle is created by this
+                                   driver.
+
+  @retval EFI_SUCCESS              The device was started.
+  @retval EFI_DEVICE_ERROR         The device could not be started due to a 
device error.Currently not implemented.
+  @retval EFI_OUT_OF_RESOURCES     The request could not be completed due to a 
lack of resources.
+  @retval Others                   The driver failded to start the device.
+
+**/
+EFI_STATUS
+EFIAPI
+UfsHcDriverBindingStart (
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
+  IN EFI_HANDLE                   Controller,
+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
+  );
+
+/**
+  Stops a device controller or a bus controller.
+
+  The Stop() function is designed to be invoked from the EFI boot service 
DisconnectController().
+  As a result, much of the error checking on the parameters to Stop() has been 
moved
+  into this common boot service. It is legal to call Stop() from other 
locations,
+  but the following calling restrictions must be followed or the system 
behavior will not be deterministic.
+  1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous 
call to this
+     same driver's Start() function.
+  2. The first NumberOfChildren handles of ChildHandleBuffer must all be a 
valid
+     EFI_HANDLE. In addition, all of these handles must have been created in 
this driver's
+     Start() function, and the Start() function must have called 
OpenProtocol() on
+     ControllerHandle with an Attribute of 
EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
+
+  @param[in]  This              A pointer to the EFI_DRIVER_BINDING_PROTOCOL 
instance.
+  @param[in]  ControllerHandle  A handle to the device being stopped. The 
handle must
+                                support a bus specific I/O protocol for the 
driver
+                                to use to stop the device.
+  @param[in]  NumberOfChildren  The number of child device handles in 
ChildHandleBuffer.
+  @param[in]  ChildHandleBuffer An array of child handles to be freed. May be 
NULL
+                                if NumberOfChildren is 0.
+
+  @retval EFI_SUCCESS           The device was stopped.
+  @retval EFI_DEVICE_ERROR      The device could not be stopped due to a 
device error.
+
+**/
+EFI_STATUS
+EFIAPI
+UfsHcDriverBindingStop (
+  IN  EFI_DRIVER_BINDING_PROTOCOL     *This,
+  IN  EFI_HANDLE                      Controller,
+  IN  UINTN                           NumberOfChildren,
+  IN  EFI_HANDLE                      *ChildHandleBuffer
+  );
+
+/**
+  Get the MMIO base of the UFS host controller.
+
+  @param[in]   This             A pointer to the 
EFI_UFS_HOST_CONTROLLER_PROTOCOL instance.
+  @param[out]  MmioBar          The MMIO base address of UFS host controller.
+
+  @retval EFI_SUCCESS           The operation succeeds.
+  @retval others                The operation fails.
+**/
+EFI_STATUS
+EFIAPI
+UfsHcGetMmioBar (
+  IN     EDKII_UFS_HOST_CONTROLLER_PROTOCOL *This,
+     OUT UINTN                              *MmioBar
+  );
+
+/**                                                                 
+  Provides the UFS controller-specific addresses needed to access system 
memory.
+            
+  @param  This                  A pointer to the 
EFI_UFS_HOST_CONTROLLER_PROTOCOL instance.
+  @param  Operation             Indicates if the bus master is going to read 
or write to system memory.
+  @param  HostAddress           The system memory address to map to the UFS 
controller.
+  @param  NumberOfBytes         On input the number of bytes to map. On output 
the number of bytes
+                                that were mapped.                              
                   
+  @param  DeviceAddress         The resulting map address for the bus master 
UFS controller to use to
+                                access the hosts HostAddress.                  
                      
+  @param  Mapping               A resulting value to pass to Unmap().
+                                  
+  @retval EFI_SUCCESS           The range was mapped for the returned 
NumberOfBytes.
+  @retval EFI_UNSUPPORTED       The HostAddress cannot be mapped as a common 
buffer.                                
+  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+  @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a 
lack of resources.
+  @retval EFI_DEVICE_ERROR      The system hardware could not map the 
requested address.
+                                   
+**/
+EFI_STATUS
+EFIAPI
+UfsHcMap (
+  IN     EDKII_UFS_HOST_CONTROLLER_PROTOCOL   *This,
+  IN     EDKII_UFS_HOST_CONTROLLER_OPERATION  Operation,
+  IN     VOID                                 *HostAddress,
+  IN OUT UINTN                                *NumberOfBytes,
+     OUT EFI_PHYSICAL_ADDRESS                 *DeviceAddress,
+     OUT VOID                                 **Mapping
+  );
+
+/**                                                                 
+  Completes the Map() operation and releases any corresponding resources.
+            
+  @param  This                  A pointer to the 
EFI_UFS_HOST_CONTROLLER_PROTOCOL instance.                                      
+  @param  Mapping               The mapping value returned from Map().
+                                  
+  @retval EFI_SUCCESS           The range was unmapped.
+  @retval EFI_DEVICE_ERROR      The data was not committed to the target 
system memory.
+                                   
+**/
+EFI_STATUS
+EFIAPI
+UfsHcUnmap (
+  IN  EDKII_UFS_HOST_CONTROLLER_PROTOCOL   *This,
+  IN  VOID                                 *Mapping
+  );
+
+/**                                                                 
+  Allocates pages that are suitable for an 
EfiUfsHcOperationBusMasterCommonBuffer
+  mapping.                                                                     
  
+            
+  @param  This                  A pointer to the 
EFI_UFS_HOST_CONTROLLER_PROTOCOL instance.
+  @param  Type                  This parameter is not used and must be ignored.
+  @param  MemoryType            The type of memory to allocate, 
EfiBootServicesData or
+                                EfiRuntimeServicesData.                        
       
+  @param  Pages                 The number of pages to allocate.               
                 
+  @param  HostAddress           A pointer to store the base system memory 
address of the
+                                allocated range.                               
         
+  @param  Attributes            The requested bit mask of attributes for the 
allocated range.
+                                  
+  @retval EFI_SUCCESS           The requested memory pages were allocated.
+  @retval EFI_UNSUPPORTED       Attributes is unsupported. The only legal 
attribute bits are
+                                MEMORY_WRITE_COMBINE and MEMORY_CACHED.        
             
+  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+  @retval EFI_OUT_OF_RESOURCES  The memory pages could not be allocated.  
+                                   
+**/
+EFI_STATUS
+EFIAPI
+UfsHcAllocateBuffer (
+  IN     EDKII_UFS_HOST_CONTROLLER_PROTOCOL *This,
+  IN     EFI_ALLOCATE_TYPE                  Type,
+  IN     EFI_MEMORY_TYPE                    MemoryType,
+  IN     UINTN                              Pages,
+     OUT VOID                               **HostAddress,
+  IN     UINT64                             Attributes
+  );
+
+/**                                                                 
+  Frees memory that was allocated with AllocateBuffer().
+            
+  @param  This                  A pointer to the 
EFI_UFS_HOST_CONTROLLER_PROTOCOL instance.  
+  @param  Pages                 The number of pages to free.                   
             
+  @param  HostAddress           The base system memory address of the 
allocated range.                                    
+                                  
+  @retval EFI_SUCCESS           The requested memory pages were freed.
+  @retval EFI_INVALID_PARAMETER The memory range specified by HostAddress and 
Pages
+                                was not allocated with AllocateBuffer().
+                                     
+**/
+EFI_STATUS
+EFIAPI
+UfsHcFreeBuffer (
+  IN  EDKII_UFS_HOST_CONTROLLER_PROTOCOL    *This,
+  IN  UINTN                                 Pages,
+  IN  VOID                                  *HostAddress
+  );
+
+/**                                                                 
+  Flushes all posted write transactions from the UFS bus to attached UFS 
device.
+            
+  @param  This                  A pointer to the 
EFI_UFS_HOST_CONTROLLER_PROTOCOL instance.  
+                                  
+  @retval EFI_SUCCESS           The posted write transactions were flushed 
from the UFS bus
+                                to attached UFS device.                        
              
+  @retval EFI_DEVICE_ERROR      The posted write transactions were not flushed 
from the UFS
+                                bus to attached UFS device due to a hardware 
error.                           
+                                     
+**/
+EFI_STATUS
+EFIAPI
+UfsHcFlush (
+  IN  EDKII_UFS_HOST_CONTROLLER_PROTOCOL   *This
+  );
+
+#endif

Added: trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcDxe/UfsPciHcDxe.inf
===================================================================
--- trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcDxe/UfsPciHcDxe.inf                 
        (rev 0)
+++ trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcDxe/UfsPciHcDxe.inf 2015-04-29 
02:42:58 UTC (rev 17246)
@@ -0,0 +1,56 @@
+## @file
+#  Component Description File For Universal Flash Storage Pci Host Controller 
Module.
+#
+#  Copyright (c) 2014 - 2015, Intel Corporation. All rights reserved.<BR>
+#
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD 
License
+#  which accompanies this distribution. The full text of the license may be 
found at
+#  http://opensource.org/licenses/bsd-license.php.
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR 
IMPLIED.
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = UfsPciHcDxe
+  MODULE_UNI_FILE                = UfsPciHcDxe.uni
+  FILE_GUID                      = AF43E178-C2E9-4712-A7CD-08BFDAC7482C
+  MODULE_TYPE                    = UEFI_DRIVER
+  VERSION_STRING                 = 0.9
+  ENTRY_POINT                    = UfsHcDriverEntry
+
+#
+# The following information is for reference only and not required by the 
build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64 IPF EBC
+#
+#  DRIVER_BINDING                =  gUfsHcDriverBinding
+#  COMPONENT_NAME                =  gUfsHcComponentName
+#  COMPONENT_NAME2               =  gUfsHcComponentName2
+
+[Sources]
+  ComponentName.c
+  UfsPciHcDxe.c
+  UfsPciHcDxe.h
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+  BaseLib
+  DebugLib
+  DevicePathLib
+  UefiDriverEntryPoint
+  UefiBootServicesTableLib
+  UefiLib
+
+[Protocols]
+  gEfiPciIoProtocolGuid                       ## TO_START
+  gEfiDevicePathProtocolGuid                  ## TO_START
+  gEdkiiUfsHostControllerProtocolGuid         ## BY_START
+
+[UserExtensions.TianoCore."ExtraFiles"]
+  UfsPciHcDxeExtra.uni
\ No newline at end of file

Added: trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcDxe/UfsPciHcDxe.uni
===================================================================
(Binary files differ)

Index: trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcDxe/UfsPciHcDxe.uni
===================================================================
--- trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcDxe/UfsPciHcDxe.uni 2015-04-29 
02:37:30 UTC (rev 17245)
+++ trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcDxe/UfsPciHcDxe.uni 2015-04-29 
02:42:58 UTC (rev 17246)

Property changes on: trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcDxe/UfsPciHcDxe.uni
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Added: trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcDxe/UfsPciHcDxeExtra.uni
===================================================================
(Binary files differ)

Index: trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcDxe/UfsPciHcDxeExtra.uni
===================================================================
--- trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcDxe/UfsPciHcDxeExtra.uni    
2015-04-29 02:37:30 UTC (rev 17245)
+++ trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcDxe/UfsPciHcDxeExtra.uni    
2015-04-29 02:42:58 UTC (rev 17246)

Property changes on: 
trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcDxe/UfsPciHcDxeExtra.uni
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Added: trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcPei/UfsPciHcPei.c
===================================================================
--- trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcPei/UfsPciHcPei.c                   
        (rev 0)
+++ trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcPei/UfsPciHcPei.c   2015-04-29 
02:42:58 UTC (rev 17246)
@@ -0,0 +1,152 @@
+/** @file
+  UfsPciHcPei driver is used to provide platform-dependent info, mainly UFS 
host controller
+  MMIO base, to upper layer UFS drivers.
+
+  Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD 
License
+  which accompanies this distribution.  The full text of the license may be 
found at
+  http://opensource.org/licenses/bsd-license.php.
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "UfsPciHcPei.h"
+
+EDKII_UFS_HOST_CONTROLLER_PPI  mUfsHostControllerPpi = { GetUfsHcMmioBar };
+
+EFI_PEI_PPI_DESCRIPTOR   mPpiList = {
+  (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+  &gEdkiiPeiUfsHostControllerPpiGuid,
+  &mUfsHostControllerPpi
+};
+
+/**
+  Get the MMIO base address of UFS host controller.
+
+  @param[in]  This               The protocol instance pointer.
+  @param[in]  ControllerId       The ID of the UFS host controller.
+  @param[out] MmioBar            Pointer to the UFS host controller MMIO base 
address.
+
+  @retval EFI_SUCCESS            The operation succeeds.
+  @retval EFI_INVALID_PARAMETER  The parameters are invalid.
+
+**/
+EFI_STATUS
+EFIAPI
+GetUfsHcMmioBar (
+  IN     EDKII_UFS_HOST_CONTROLLER_PPI *This,
+  IN     UINT8                         ControllerId,
+     OUT UINTN                         *MmioBar
+  )
+{
+  UFS_HC_PEI_PRIVATE_DATA  *Private;
+
+  if ((This == NULL) || (MmioBar == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Private = UFS_HC_PEI_PRIVATE_DATA_FROM_THIS (This);
+
+  if (ControllerId >= Private->TotalUfsHcs) {
+    return EFI_INVALID_PARAMETER;
+  }
+  
+  *MmioBar = (UINTN)Private->UfsHcPciAddr[ControllerId];
+
+  return EFI_SUCCESS;
+}
+
+/**
+  The user code starts with this function.
+  
+  @param  FileHandle             Handle of the file being invoked.
+  @param  PeiServices            Describes the list of possible PEI Services.
+
+  @retval EFI_SUCCESS            The driver is successfully initialized.
+  @retval Others                 Can't initialize the driver.
+
+**/
+EFI_STATUS
+EFIAPI
+InitializeUfsHcPeim (
+  IN EFI_PEI_FILE_HANDLE       FileHandle,
+  IN CONST EFI_PEI_SERVICES    **PeiServices
+  )
+{
+  EFI_BOOT_MODE            BootMode;
+  EFI_STATUS               Status;
+  UINT16                   Bus;
+  UINT16                   Device;
+  UINT16                   Function;
+  UINT32                   Size;
+  UINT8                    SubClass;
+  UINT8                    BaseClass;
+  UFS_HC_PEI_PRIVATE_DATA  *Private;
+
+  //
+  // Shadow this PEIM to run from memory
+  //
+  if (!EFI_ERROR (PeiServicesRegisterForShadow (FileHandle))) {
+    return EFI_SUCCESS;
+  }
+
+  Status = PeiServicesGetBootMode (&BootMode);
+  ///
+  /// We do not export this in S3 boot path, because it is only for recovery.
+  ///
+  if (BootMode == BOOT_ON_S3_RESUME) {
+    return EFI_SUCCESS;
+  }
+
+  Private = (UFS_HC_PEI_PRIVATE_DATA *) AllocateZeroPool (sizeof 
(UFS_HC_PEI_PRIVATE_DATA));
+  if (Private == NULL) {
+    DEBUG ((EFI_D_ERROR, "Failed to allocate memory for 
UFS_HC_PEI_PRIVATE_DATA! \n"));
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  Private->Signature            = UFS_HC_PEI_SIGNATURE;
+  Private->UfsHostControllerPpi = mUfsHostControllerPpi;
+  Private->PpiList              = mPpiList;
+  Private->PpiList.Ppi          = &Private->UfsHostControllerPpi;
+
+  for (Bus = 0; Bus < 256; Bus++) {
+    for (Device = 0; Device < 32; Device++) {
+      for (Function = 0; Function < 8; Function++) {
+        SubClass  = PciRead8 (PCI_LIB_ADDRESS (Bus, Device, Function, 0x0A));
+        BaseClass = PciRead8 (PCI_LIB_ADDRESS (Bus, Device, Function, 0x0B));
+
+        if ((SubClass == 0x09) && (BaseClass == PCI_CLASS_MASS_STORAGE)) {
+          //
+          // Get the Ufs Pci host controller's MMIO region size.
+          //
+          PciAnd16 (PCI_LIB_ADDRESS (Bus, Device, Function, 
PCI_COMMAND_OFFSET), (UINT16)~(EFI_PCI_COMMAND_BUS_MASTER | 
EFI_PCI_COMMAND_MEMORY_SPACE));
+          PciWrite32 (PCI_LIB_ADDRESS (Bus, Device, Function, 
PCI_BASE_ADDRESSREG_OFFSET), 0xFFFFFFFF);
+          Size = PciRead32 (PCI_LIB_ADDRESS (Bus, Device, Function, 
PCI_BASE_ADDRESSREG_OFFSET));
+          //
+          // Assign resource to the Ufs Pci host controller's MMIO BAR.
+          // Enable the Ufs Pci host controller by setting BME and MSE bits of 
PCI_CMD register.
+          //
+          PciWrite32 (PCI_LIB_ADDRESS (Bus, Device, Function, 
PCI_BASE_ADDRESSREG_OFFSET), (UINT32)(PcdGet32 
(PcdUfsPciHostControllerMmioBase) + Size * Private->TotalUfsHcs));
+          PciOr16 (PCI_LIB_ADDRESS (Bus, Device, Function, 
PCI_COMMAND_OFFSET), (EFI_PCI_COMMAND_BUS_MASTER | 
EFI_PCI_COMMAND_MEMORY_SPACE));
+          //
+          // Record the allocated Mmio base address.
+          //
+          Private->UfsHcPciAddr[Private->TotalUfsHcs] = PcdGet32 
(PcdUfsPciHostControllerMmioBase) + Size * Private->TotalUfsHcs;
+          Private->TotalUfsHcs++;
+          ASSERT (Private->TotalUfsHcs < MAX_UFS_HCS);
+        }
+      }
+    }
+  }
+
+  ///
+  /// Install Ufs Host Controller PPI
+  ///
+  Status = PeiServicesInstallPpi (&Private->PpiList);
+
+  ASSERT_EFI_ERROR (Status);
+  return Status;
+}

Added: trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcPei/UfsPciHcPei.h
===================================================================
--- trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcPei/UfsPciHcPei.h                   
        (rev 0)
+++ trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcPei/UfsPciHcPei.h   2015-04-29 
02:42:58 UTC (rev 17246)
@@ -0,0 +1,62 @@
+/** @file
+  Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD 
License
+  which accompanies this distribution.  The full text of the license may be 
found at
+  http://opensource.org/licenses/bsd-license.php.
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _UFS_PCI_HOST_CONTROLLER_PEI_H_
+#define _UFS_PCI_HOST_CONTROLLER_PEI_H_
+
+#include <PiPei.h>
+
+#include <Ppi/MasterBootMode.h>
+#include <Ppi/UfsHostController.h>
+
+#include <IndustryStandard/Pci.h>
+
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/PciLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/MemoryAllocationLib.h>
+
+#define UFS_HC_PEI_SIGNATURE    SIGNATURE_32 ('U', 'F', 'S', 'P')
+#define MAX_UFS_HCS             8
+
+typedef struct {
+  UINTN                         Signature;
+  EDKII_UFS_HOST_CONTROLLER_PPI UfsHostControllerPpi;
+  EFI_PEI_PPI_DESCRIPTOR        PpiList;
+  UINTN                         TotalUfsHcs;
+  UINTN                         UfsHcPciAddr[MAX_UFS_HCS];
+} UFS_HC_PEI_PRIVATE_DATA;
+
+#define UFS_HC_PEI_PRIVATE_DATA_FROM_THIS(a)  CR (a, UFS_HC_PEI_PRIVATE_DATA, 
UfsHostControllerPpi, UFS_HC_PEI_SIGNATURE)
+
+/**
+  Get the MMIO base address of UFS host controller.
+
+  @param[in]  This               The protocol instance pointer.
+  @param[in]  ControllerId       The ID of the UFS host controller.
+  @param[out] MmioBar            Pointer to the UFS host controller MMIO base 
address.
+
+  @retval EFI_SUCCESS            The operation succeeds.
+  @retval EFI_INVALID_PARAMETER  The parameters are invalid.
+
+**/
+EFI_STATUS
+EFIAPI
+GetUfsHcMmioBar (
+  IN     EDKII_UFS_HOST_CONTROLLER_PPI *This,
+  IN     UINT8                         ControllerId,
+     OUT UINTN                         *MmioBar
+  );
+
+#endif

Added: trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcPei/UfsPciHcPei.inf
===================================================================
--- trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcPei/UfsPciHcPei.inf                 
        (rev 0)
+++ trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcPei/UfsPciHcPei.inf 2015-04-29 
02:42:58 UTC (rev 17246)
@@ -0,0 +1,56 @@
+## @file
+#  Component Description File For Universal Flash Storage Pci Host Controller 
Pei Module.
+#
+#  Copyright (c) 2014 - 2015, Intel Corporation. All rights reserved.<BR>
+#
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD 
License
+#  which accompanies this distribution. The full text of the license may be 
found at
+#  http://opensource.org/licenses/bsd-license.php.
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR 
IMPLIED.
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = UfsPciHcPei
+  MODULE_UNI_FILE                = UfsPciHcPei.uni
+  FILE_GUID                      = 905DC1AD-C44D-4965-98AC-B6B4444BFD65
+  MODULE_TYPE                    = PEIM
+  VERSION_STRING                 = 0.9
+
+  ENTRY_POINT                    = InitializeUfsHcPeim
+
+#
+# The following information is for reference only and not required by the 
build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64 IPF EBC
+#
+
+[Sources]
+  UfsPciHcPei.c
+  UfsPciHcPei.h
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+  PciLib
+  DebugLib
+  PeiServicesLib
+  MemoryAllocationLib
+  PeimEntryPoint
+
+[Pcd]
+  gEfiMdeModulePkgTokenSpaceGuid.PcdUfsPciHostControllerMmioBase   ## CONSUMES
+
+[Ppis]
+  gEdkiiPeiUfsHostControllerPpiGuid         ## PRODUCES
+
+[Depex]
+  gEfiPeiMasterBootModePpiGuid AND gEfiPeiMemoryDiscoveredPpiGuid
+
+[UserExtensions.TianoCore."ExtraFiles"]
+  UfsPciHcPeiExtra.uni
\ No newline at end of file

Added: trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcPei/UfsPciHcPei.uni
===================================================================
(Binary files differ)

Index: trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcPei/UfsPciHcPei.uni
===================================================================
--- trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcPei/UfsPciHcPei.uni 2015-04-29 
02:37:30 UTC (rev 17245)
+++ trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcPei/UfsPciHcPei.uni 2015-04-29 
02:42:58 UTC (rev 17246)

Property changes on: trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcPei/UfsPciHcPei.uni
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Added: trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcPei/UfsPciHcPeiExtra.uni
===================================================================
(Binary files differ)

Index: trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcPei/UfsPciHcPeiExtra.uni
===================================================================
--- trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcPei/UfsPciHcPeiExtra.uni    
2015-04-29 02:37:30 UTC (rev 17245)
+++ trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcPei/UfsPciHcPeiExtra.uni    
2015-04-29 02:42:58 UTC (rev 17246)

Property changes on: 
trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcPei/UfsPciHcPeiExtra.uni
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Added: trunk/edk2/MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsBlockIoPei.c
===================================================================
--- trunk/edk2/MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsBlockIoPei.c               
                (rev 0)
+++ trunk/edk2/MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsBlockIoPei.c       
2015-04-29 02:42:58 UTC (rev 17246)
@@ -0,0 +1,995 @@
+/** @file
+
+  Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD 
License
+  which accompanies this distribution.  The full text of the license may be 
found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "UfsBlockIoPei.h"
+
+//
+// Template for UFS HC Peim Private Data.
+//
+UFS_PEIM_HC_PRIVATE_DATA   gUfsHcPeimTemplate = {
+  UFS_PEIM_HC_SIG,                // Signature
+  NULL,                           // Controller
+  NULL,                           // Pool
+  {                               // BlkIoPpi
+    UfsBlockIoPeimGetDeviceNo,
+    UfsBlockIoPeimGetMediaInfo,
+    UfsBlockIoPeimReadBlocks
+  },
+  {                               // BlkIoPpiList
+    EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
+    &gEfiPeiVirtualBlockIoPpiGuid,
+    NULL
+  },
+  {                               // Media
+    {
+      UfsDevice,
+      TRUE,
+      0,
+      0x1000
+    },
+    {
+      UfsDevice,
+      TRUE,
+      0,
+      0x1000
+    },
+    {
+      UfsDevice,
+      TRUE,
+      0,
+      0x1000
+    },
+    {
+      UfsDevice,
+      TRUE,
+      0,
+      0x1000
+    },
+    {
+      UfsDevice,
+      TRUE,
+      0,
+      0x1000
+    },
+    {
+      UfsDevice,
+      TRUE,
+      0,
+      0x1000
+    },
+    {
+      UfsDevice,
+      TRUE,
+      0,
+      0x1000
+    },
+    {
+      UfsDevice,
+      TRUE,
+      0,
+      0x1000
+    }
+  },
+  0,                              // UfsHcBase
+  0,                              // Capabilities
+  0,                              // TaskTag
+  0,                              // UtpTrlBase
+  0,                              // Nutrs
+  0,                              // UtpTmrlBase
+  0,                              // Nutmrs
+  {                               // Luns
+    {
+      UFS_LUN_0,                      // Ufs Common Lun 0
+      UFS_LUN_1,                      // Ufs Common Lun 1
+      UFS_LUN_2,                      // Ufs Common Lun 2
+      UFS_LUN_3,                      // Ufs Common Lun 3
+      UFS_LUN_4,                      // Ufs Common Lun 4
+      UFS_LUN_5,                      // Ufs Common Lun 5
+      UFS_LUN_6,                      // Ufs Common Lun 6
+      UFS_LUN_7,                      // Ufs Common Lun 7
+    },
+    0x0000,                           // By default exposing all Luns.
+    0x0
+  }
+};
+
+/**
+  Execute Request Sense SCSI command on a specific UFS device.
+
+  @param[in]  Private              A pointer to UFS_PEIM_HC_PRIVATE_DATA data 
structure.
+  @param[in]  Lun                  The lun on which the SCSI cmd executed.
+  @param[out] DataBuffer           A pointer to output sense data.
+  @param[out] DataBufferLength     The length of output sense data.
+
+  @retval EFI_SUCCESS              The command executed successfully.
+  @retval EFI_DEVICE_ERROR         A device error occurred while attempting to 
send SCSI Request Packet.
+  @retval EFI_TIMEOUT              A timeout occurred while waiting for the 
SCSI Request Packet to execute.
+
+**/
+EFI_STATUS
+UfsPeimRequestSense (
+  IN     UFS_PEIM_HC_PRIVATE_DATA        *Private,
+  IN     UINTN                           Lun,  
+     OUT VOID                            *DataBuffer,
+     OUT UINT32                          *DataBufferLength
+  )  
+{
+  UFS_SCSI_REQUEST_PACKET                Packet;
+  UINT8                                  Cdb[UFS_SCSI_OP_LENGTH_SIX];
+  EFI_STATUS                             Status;
+
+  ZeroMem (&Packet, sizeof (UFS_SCSI_REQUEST_PACKET));
+  ZeroMem (Cdb, sizeof (Cdb));
+
+  Cdb[0]  = EFI_SCSI_OP_REQUEST_SENSE;
+
+  Packet.Timeout          = UFS_TIMEOUT;
+  Packet.Cdb              = Cdb;
+  Packet.CdbLength        = sizeof (Cdb);
+  Packet.DataDirection    = UfsDataIn;
+  Packet.InDataBuffer     = DataBuffer;
+  Packet.InTransferLength = *DataBufferLength;
+  Packet.SenseData        = NULL;
+  Packet.SenseDataLength  = 0;
+
+  Status = UfsExecScsiCmds (Private,(UINT8)Lun, &Packet);
+
+  if (!EFI_ERROR (Status)) {
+    *DataBufferLength = Packet.InTransferLength;
+  }
+
+  return Status;
+}
+
+/**
+  Execute TEST UNITY READY SCSI command on a specific UFS device.
+
+  @param[in]  Private              A pointer to UFS_PEIM_HC_PRIVATE_DATA data 
structure.
+  @param[in]  Lun                  The lun on which the SCSI cmd executed.
+  @param[out] SenseData            A pointer to output sense data.
+  @param[out] SenseDataLength      The length of output sense data.
+
+  @retval EFI_SUCCESS              The command executed successfully.
+  @retval EFI_DEVICE_ERROR         A device error occurred while attempting to 
send SCSI Request Packet.
+  @retval EFI_TIMEOUT              A timeout occurred while waiting for the 
SCSI Request Packet to execute.
+
+**/
+EFI_STATUS
+UfsPeimTestUnitReady (
+  IN     UFS_PEIM_HC_PRIVATE_DATA        *Private,
+  IN     UINTN                           Lun,  
+     OUT VOID                            *SenseData,  OPTIONAL
+     OUT UINT8                           *SenseDataLength
+  )  
+{
+  UFS_SCSI_REQUEST_PACKET                Packet;
+  UINT8                                  Cdb[UFS_SCSI_OP_LENGTH_SIX];
+  EFI_STATUS                             Status;
+
+  ZeroMem (&Packet, sizeof (UFS_SCSI_REQUEST_PACKET));
+  ZeroMem (Cdb, sizeof (Cdb));
+
+  Cdb[0]  = EFI_SCSI_OP_TEST_UNIT_READY;
+
+  Packet.Timeout         = UFS_TIMEOUT;
+  Packet.Cdb             = Cdb;
+  Packet.CdbLength       = sizeof (Cdb);
+  Packet.DataDirection   = UfsNoData;
+  Packet.SenseData       = SenseData;
+  Packet.SenseDataLength = *SenseDataLength;
+
+  Status = UfsExecScsiCmds (Private,(UINT8)Lun, &Packet);
+
+  if (*SenseDataLength != 0) {
+    *SenseDataLength = Packet.SenseDataLength;
+  }
+
+  return Status;
+}
+
+/**
+  Execute INQUIRY SCSI command on a specific UFS device.
+
+  @param[in]  Private              A pointer to UFS_PEIM_HC_PRIVATE_DATA data 
structure.
+  @param[in]  Lun                  The lun on which the SCSI cmd executed.
+  @param[out] Inquiry              A pointer to Inquiry data buffer.
+  @param[out] InquiryLengths       The length of output Inquiry data.
+  @param[out] SenseData            A pointer to output sense data.
+  @param[out] SenseDataLength      The length of output sense data.
+
+  @retval EFI_SUCCESS              The command executed successfully.
+  @retval EFI_DEVICE_ERROR         A device error occurred while attempting to 
send SCSI Request Packet.
+  @retval EFI_TIMEOUT              A timeout occurred while waiting for the 
SCSI Request Packet to execute.
+
+**/
+EFI_STATUS
+UfsPeimInquiry (
+  IN     UFS_PEIM_HC_PRIVATE_DATA     *Private,
+  IN     UINTN                        Lun,
+     OUT VOID                         *Inquiry,
+     OUT UINT32                       *InquiryLength,
+     OUT VOID                         *SenseData,  OPTIONAL
+     OUT UINT8                        *SenseDataLength
+  )  
+{
+  UFS_SCSI_REQUEST_PACKET             Packet;
+  UINT8                               Cdb[UFS_SCSI_OP_LENGTH_SIX];
+  EFI_STATUS                          Status;
+
+  ZeroMem (&Packet, sizeof (UFS_SCSI_REQUEST_PACKET));
+  ZeroMem (Cdb, sizeof (Cdb));
+
+  Cdb[0]  = EFI_SCSI_OP_INQUIRY;
+  Cdb[4]  = sizeof (EFI_SCSI_INQUIRY_DATA);
+
+  Packet.Timeout          = UFS_TIMEOUT;
+  Packet.Cdb              = Cdb;
+  Packet.CdbLength        = sizeof (Cdb);
+  Packet.InDataBuffer     = Inquiry;
+  Packet.InTransferLength = *InquiryLength;
+  Packet.DataDirection    = UfsDataIn;
+  Packet.SenseData        = SenseData;
+  Packet.SenseDataLength  = *SenseDataLength;
+
+  Status = UfsExecScsiCmds (Private, (UINT8)Lun, &Packet);
+
+  if (*SenseDataLength != 0) {
+    *SenseDataLength = Packet.SenseDataLength;
+  }
+
+  if (!EFI_ERROR (Status)) {
+    *InquiryLength = Packet.InTransferLength;
+  }
+
+  return Status;
+}
+
+/**
+  Execute READ CAPACITY(10) SCSI command on a specific UFS device.
+
+  @param[in]  Private              A pointer to UFS_PEIM_HC_PRIVATE_DATA data 
structure.
+  @param[in]  Lun                  The lun on which the SCSI cmd executed.
+  @param[out] DataBuffer           A pointer to READ_CAPACITY data buffer.
+  @param[out] DataLength           The length of output READ_CAPACITY data.
+  @param[out] SenseData            A pointer to output sense data.
+  @param[out] SenseDataLength      The length of output sense data.
+
+  @retval EFI_SUCCESS              The command executed successfully.
+  @retval EFI_DEVICE_ERROR         A device error occurred while attempting to 
send SCSI Request Packet.
+  @retval EFI_TIMEOUT              A timeout occurred while waiting for the 
SCSI Request Packet to execute.
+
+**/
+EFI_STATUS
+UfsPeimReadCapacity (
+  IN     UFS_PEIM_HC_PRIVATE_DATA     *Private,
+  IN     UINTN                        Lun,
+     OUT VOID                         *DataBuffer,
+     OUT UINT32                       *DataLength,
+     OUT VOID                         *SenseData,  OPTIONAL
+     OUT UINT8                        *SenseDataLength
+  )  
+{
+  UFS_SCSI_REQUEST_PACKET             Packet;
+  UINT8                               Cdb[UFS_SCSI_OP_LENGTH_TEN];
+  EFI_STATUS                          Status;
+
+  ZeroMem (&Packet, sizeof (UFS_SCSI_REQUEST_PACKET));
+  ZeroMem (Cdb, sizeof (Cdb));
+
+  Cdb[0] = EFI_SCSI_OP_READ_CAPACITY;
+
+  Packet.Timeout          = UFS_TIMEOUT;
+  Packet.Cdb              = Cdb;
+  Packet.CdbLength        = sizeof (Cdb);
+  Packet.InDataBuffer     = DataBuffer;
+  Packet.InTransferLength = *DataLength;
+  Packet.DataDirection    = UfsDataIn;
+  Packet.SenseData        = SenseData;
+  Packet.SenseDataLength  = *SenseDataLength;
+
+  Status = UfsExecScsiCmds (Private, (UINT8)Lun, &Packet);
+
+  if (*SenseDataLength != 0) {
+    *SenseDataLength = Packet.SenseDataLength;
+  }
+
+  if (!EFI_ERROR (Status)) {
+    *DataLength = Packet.InTransferLength;
+  }
+
+  return Status;
+}
+
+/**
+  Execute READ CAPACITY(16) SCSI command on a specific UFS device.
+
+  @param[in]  Private              A pointer to UFS_PEIM_HC_PRIVATE_DATA data 
structure.
+  @param[in]  Lun                  The lun on which the SCSI cmd executed.
+  @param[out] DataBuffer           A pointer to READ_CAPACITY data buffer.
+  @param[out] DataLength           The length of output READ_CAPACITY data.
+  @param[out] SenseData            A pointer to output sense data.
+  @param[out] SenseDataLength      The length of output sense data.
+
+  @retval EFI_SUCCESS              The command executed successfully.
+  @retval EFI_DEVICE_ERROR         A device error occurred while attempting to 
send SCSI Request Packet.
+  @retval EFI_TIMEOUT              A timeout occurred while waiting for the 
SCSI Request Packet to execute.
+
+**/
+EFI_STATUS
+UfsPeimReadCapacity16 (
+  IN     UFS_PEIM_HC_PRIVATE_DATA     *Private,
+  IN     UINTN                        Lun,
+     OUT VOID                         *DataBuffer,
+     OUT UINT32                       *DataLength,
+     OUT VOID                         *SenseData,  OPTIONAL
+     OUT UINT8                        *SenseDataLength
+  )  
+{
+  UFS_SCSI_REQUEST_PACKET             Packet;
+  UINT8                               Cdb[UFS_SCSI_OP_LENGTH_SIXTEEN];
+  EFI_STATUS                          Status;
+
+  ZeroMem (&Packet, sizeof (UFS_SCSI_REQUEST_PACKET));
+  ZeroMem (Cdb, sizeof (Cdb));
+
+  Cdb[0]  = EFI_SCSI_OP_READ_CAPACITY16;
+  Cdb[1]  = 0x10;          // Service Action should be 0x10 for UFS device.
+  Cdb[13] = 0x20;          // The maximum number of bytes for returned data.
+
+  Packet.Timeout          = UFS_TIMEOUT;
+  Packet.Cdb              = Cdb;
+  Packet.CdbLength        = sizeof (Cdb);
+  Packet.InDataBuffer     = DataBuffer;
+  Packet.InTransferLength = *DataLength;
+  Packet.DataDirection    = UfsDataIn;
+  Packet.SenseData        = SenseData;
+  Packet.SenseDataLength  = *SenseDataLength;
+
+  Status = UfsExecScsiCmds (Private, (UINT8)Lun, &Packet);
+
+  if (*SenseDataLength != 0) {
+    *SenseDataLength = Packet.SenseDataLength;
+  }
+
+  if (!EFI_ERROR (Status)) {
+    *DataLength = Packet.InTransferLength;
+  }
+
+  return Status;
+}
+
+/**
+  Execute READ (10) SCSI command on a specific UFS device.
+
+  @param[in]  Private              A pointer to UFS_PEIM_HC_PRIVATE_DATA data 
structure.
+  @param[in]  Lun                  The lun on which the SCSI cmd executed.
+  @param[in]  StartLba             The start LBA.
+  @param[in]  SectorNum            The sector number to be read.
+  @param[out] DataBuffer           A pointer to data buffer.
+  @param[out] DataLength           The length of output data.
+  @param[out] SenseData            A pointer to output sense data.
+  @param[out] SenseDataLength      The length of output sense data.
+
+  @retval EFI_SUCCESS              The command executed successfully.
+  @retval EFI_DEVICE_ERROR         A device error occurred while attempting to 
send SCSI Request Packet.
+  @retval EFI_TIMEOUT              A timeout occurred while waiting for the 
SCSI Request Packet to execute.
+
+**/
+EFI_STATUS
+UfsPeimRead10 (
+  IN     UFS_PEIM_HC_PRIVATE_DATA     *Private,
+  IN     UINTN                        Lun,
+  IN     UINTN                        StartLba,
+  IN     UINT32                       SectorNum,
+     OUT VOID                         *DataBuffer,
+     OUT UINT32                       *DataLength,
+     OUT VOID                         *SenseData,  OPTIONAL
+     OUT UINT8                        *SenseDataLength
+  )  
+{
+  UFS_SCSI_REQUEST_PACKET             Packet;
+  UINT8                               Cdb[UFS_SCSI_OP_LENGTH_TEN];
+  EFI_STATUS                          Status;
+
+  ZeroMem (&Packet, sizeof (UFS_SCSI_REQUEST_PACKET));
+  ZeroMem (Cdb, sizeof (Cdb));
+
+  Cdb[0] = EFI_SCSI_OP_READ10;
+  WriteUnaligned32 ((UINT32 *)&Cdb[2], SwapBytes32 ((UINT32) StartLba));
+  WriteUnaligned16 ((UINT16 *)&Cdb[7], SwapBytes16 ((UINT16) SectorNum));
+
+  Packet.Timeout          = UFS_TIMEOUT;
+  Packet.Cdb              = Cdb;
+  Packet.CdbLength        = sizeof (Cdb);
+  Packet.InDataBuffer     = DataBuffer;
+  Packet.InTransferLength = *DataLength;
+  Packet.DataDirection    = UfsDataIn;
+  Packet.SenseData        = SenseData;
+  Packet.SenseDataLength  = *SenseDataLength;
+
+  Status = UfsExecScsiCmds (Private, (UINT8)Lun, &Packet);
+
+  if (*SenseDataLength != 0) {
+    *SenseDataLength = Packet.SenseDataLength;
+  }
+
+  if (!EFI_ERROR (Status)) {
+    *DataLength = Packet.InTransferLength;
+  }
+
+  return Status;
+}
+
+/**
+  Execute READ (16) SCSI command on a specific UFS device.
+
+  @param[in]  Private              A pointer to UFS_PEIM_HC_PRIVATE_DATA data 
structure.
+  @param[in]  Lun                  The lun on which the SCSI cmd executed.
+  @param[in]  StartLba             The start LBA.
+  @param[in]  SectorNum            The sector number to be read.
+  @param[out] DataBuffer           A pointer to data buffer.
+  @param[out] DataLength           The length of output data.
+  @param[out] SenseData            A pointer to output sense data.
+  @param[out] SenseDataLength      The length of output sense data.
+
+  @retval EFI_SUCCESS              The command executed successfully.
+  @retval EFI_DEVICE_ERROR         A device error occurred while attempting to 
send SCSI Request Packet.
+  @retval EFI_TIMEOUT              A timeout occurred while waiting for the 
SCSI Request Packet to execute.
+
+**/
+EFI_STATUS
+UfsPeimRead16 (
+  IN     UFS_PEIM_HC_PRIVATE_DATA     *Private,
+  IN     UINTN                        Lun,
+  IN     UINTN                        StartLba,
+  IN     UINT32                       SectorNum,
+     OUT VOID                         *DataBuffer,
+     OUT UINT32                       *DataLength,
+     OUT VOID                         *SenseData,  OPTIONAL
+     OUT UINT8                        *SenseDataLength
+  )  
+{
+  UFS_SCSI_REQUEST_PACKET             Packet;
+  UINT8                               Cdb[UFS_SCSI_OP_LENGTH_SIXTEEN];
+  EFI_STATUS                          Status;
+
+  ZeroMem (&Packet, sizeof (UFS_SCSI_REQUEST_PACKET));
+  ZeroMem (Cdb, sizeof (Cdb));
+
+  Cdb[0] = EFI_SCSI_OP_READ16;
+  WriteUnaligned64 ((UINT64 *)&Cdb[2], SwapBytes64 (StartLba));
+  WriteUnaligned32 ((UINT32 *)&Cdb[10], SwapBytes32 (SectorNum));
+
+  Packet.Timeout          = UFS_TIMEOUT;
+  Packet.Cdb              = Cdb;
+  Packet.CdbLength        = sizeof (Cdb);
+  Packet.InDataBuffer     = DataBuffer;
+  Packet.InTransferLength = *DataLength;
+  Packet.DataDirection    = UfsDataIn;
+  Packet.SenseData        = SenseData;
+  Packet.SenseDataLength  = *SenseDataLength;
+
+  Status = UfsExecScsiCmds (Private, (UINT8)Lun, &Packet);
+
+  if (*SenseDataLength != 0) {
+    *SenseDataLength = Packet.SenseDataLength;
+  }
+
+  if (!EFI_ERROR (Status)) {
+    *DataLength = Packet.InTransferLength;
+  }
+
+  return Status;
+}
+
+/**
+  Parsing Sense Keys from sense data.
+
+  @param  Media              The pointer of EFI_PEI_BLOCK_IO_MEDIA
+  @param  SenseData          The pointer of EFI_SCSI_SENSE_DATA
+  @param  NeedRetry          The pointer of action which indicates what is 
need to retry
+
+  @retval EFI_DEVICE_ERROR   Indicates that error occurs
+  @retval EFI_SUCCESS        Successfully to complete the parsing
+
+**/
+EFI_STATUS
+UfsPeimParsingSenseKeys (
+  IN     EFI_PEI_BLOCK_IO_MEDIA    *Media,
+  IN     EFI_SCSI_SENSE_DATA       *SenseData,
+     OUT BOOLEAN                   *NeedRetry
+  )
+{
+  if ((SenseData->Sense_Key == EFI_SCSI_SK_NOT_READY) &&
+      (SenseData->Addnl_Sense_Code == EFI_SCSI_ASC_NO_MEDIA)) {
+    Media->MediaPresent = FALSE;
+    *NeedRetry = FALSE;
+    DEBUG ((EFI_D_VERBOSE, "UfsBlockIoPei: Is No Media\n"));
+    return EFI_DEVICE_ERROR;
+  }
+
+  if ((SenseData->Sense_Key == EFI_SCSI_SK_UNIT_ATTENTION) &&
+      (SenseData->Addnl_Sense_Code == EFI_SCSI_ASC_MEDIA_CHANGE)) {
+    *NeedRetry = TRUE;
+    DEBUG ((EFI_D_VERBOSE, "UfsBlockIoPei: Is Media Change\n"));
+    return EFI_SUCCESS;
+  }
+
+  if ((SenseData->Sense_Key == EFI_SCSI_SK_UNIT_ATTENTION) &&
+      (SenseData->Addnl_Sense_Code == EFI_SCSI_ASC_RESET)) {
+    *NeedRetry = TRUE;
+    DEBUG ((EFI_D_VERBOSE, "UfsBlockIoPei: Was Reset Before\n"));
+    return EFI_SUCCESS;
+  }
+
+  if ((SenseData->Sense_Key == EFI_SCSI_SK_MEDIUM_ERROR) ||
+      ((SenseData->Sense_Key == EFI_SCSI_SK_NOT_READY) &&
+      (SenseData->Addnl_Sense_Code == EFI_SCSI_ASC_MEDIA_UPSIDE_DOWN))) {
+    *NeedRetry = FALSE;
+    DEBUG ((EFI_D_VERBOSE, "UfsBlockIoPei: Media Error\n"));
+    return EFI_DEVICE_ERROR;
+  }
+
+  if (SenseData->Sense_Key == EFI_SCSI_SK_HARDWARE_ERROR) {
+    *NeedRetry = FALSE;
+    DEBUG ((EFI_D_VERBOSE, "UfsBlockIoPei: Hardware Error\n"));
+    return EFI_DEVICE_ERROR;
+  }
+
+  if ((SenseData->Sense_Key == EFI_SCSI_SK_NOT_READY) &&
+      (SenseData->Addnl_Sense_Code == EFI_SCSI_ASC_NOT_READY) &&
+      (SenseData->Addnl_Sense_Code_Qualifier == EFI_SCSI_ASCQ_IN_PROGRESS)) {
+    *NeedRetry = TRUE;
+    DEBUG ((EFI_D_VERBOSE, "UfsBlockIoPei: Was Reset Before\n"));
+    return EFI_SUCCESS;
+  }
+
+  *NeedRetry = FALSE;
+  DEBUG ((EFI_D_VERBOSE, "UfsBlockIoPei: Sense Key = 0x%x ASC = 0x%x!\n", 
SenseData->Sense_Key, SenseData->Addnl_Sense_Code));
+  return EFI_DEVICE_ERROR;
+}
+
+
+/**
+  Gets the count of block I/O devices that one specific block driver detects.
+
+  This function is used for getting the count of block I/O devices that one 
+  specific block driver detects.  To the PEI ATAPI driver, it returns the 
number
+  of all the detected ATAPI devices it detects during the enumeration process. 
+  To the PEI legacy floppy driver, it returns the number of all the legacy 
+  devices it finds during its enumeration process. If no device is detected, 
+  then the function will return zero.  
+  
+  @param[in]  PeiServices          General-purpose services that are available 
+                                   to every PEIM.
+  @param[in]  This                 Indicates the EFI_PEI_RECOVERY_BLOCK_IO_PPI 
+                                   instance.
+  @param[out] NumberBlockDevices   The number of block I/O devices discovered.
+
+  @retval     EFI_SUCCESS          The operation performed successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+UfsBlockIoPeimGetDeviceNo (
+  IN  EFI_PEI_SERVICES               **PeiServices,
+  IN  EFI_PEI_RECOVERY_BLOCK_IO_PPI  *This,
+  OUT UINTN                          *NumberBlockDevices
+  )
+{
+  //
+  // For Ufs device, it has up to 8 normal Luns plus some well-known Luns.
+  // At PEI phase, we will only expose normal Luns to user.
+  // For those disabled Lun, when user try to access it, the operation would 
fail.
+  //
+  *NumberBlockDevices = UFS_PEIM_MAX_LUNS;
+  return EFI_SUCCESS;
+}
+
+/**
+  Gets a block device's media information.
+
+  This function will provide the caller with the specified block device's 
media 
+  information. If the media changes, calling this function will update the 
media 
+  information accordingly.
+
+  @param[in]  PeiServices   General-purpose services that are available to 
every
+                            PEIM
+  @param[in]  This          Indicates the EFI_PEI_RECOVERY_BLOCK_IO_PPI 
instance.
+  @param[in]  DeviceIndex   Specifies the block device to which the function 
wants 
+                            to talk. Because the driver that implements Block 
I/O 
+                            PPIs will manage multiple block devices, the PPIs 
that 
+                            want to talk to a single device must specify the 
+                            device index that was assigned during the 
enumeration
+                            process. This index is a number from one to 
+                            NumberBlockDevices.
+  @param[out] MediaInfo     The media information of the specified block 
media.  
+                            The caller is responsible for the ownership of 
this 
+                            data structure.
+
+  @par Note: 
+      The MediaInfo structure describes an enumeration of possible block 
device 
+      types.  This enumeration exists because no device paths are actually 
passed 
+      across interfaces that describe the type or class of hardware that is 
publishing 
+      the block I/O interface. This enumeration will allow for policy decisions
+      in the Recovery PEIM, such as "Try to recover from legacy floppy first, 
+      LS-120 second, CD-ROM third." If there are multiple partitions 
abstracted 
+      by a given device type, they should be reported in ascending order; this 
+      order also applies to nested partitions, such as legacy MBR, where the 
+      outermost partitions would have precedence in the reporting order. The 
+      same logic applies to systems such as IDE that have precedence 
relationships 
+      like "Master/Slave" or "Primary/Secondary". The master device should be 
+      reported first, the slave second.
+  
+  @retval EFI_SUCCESS        Media information about the specified block 
device 
+                             was obtained successfully.
+  @retval EFI_DEVICE_ERROR   Cannot get the media information due to a 
hardware 
+                             error.
+
+**/
+EFI_STATUS
+EFIAPI
+UfsBlockIoPeimGetMediaInfo (
+  IN  EFI_PEI_SERVICES               **PeiServices,
+  IN  EFI_PEI_RECOVERY_BLOCK_IO_PPI  *This,
+  IN  UINTN                          DeviceIndex,
+  OUT EFI_PEI_BLOCK_IO_MEDIA         *MediaInfo
+  )
+{
+  EFI_STATUS                         Status;
+  UFS_PEIM_HC_PRIVATE_DATA           *Private;
+  EFI_SCSI_SENSE_DATA                SenseData;
+  UINT8                              SenseDataLength;
+  EFI_SCSI_DISK_CAPACITY_DATA        Capacity;
+  EFI_SCSI_DISK_CAPACITY_DATA16      Capacity16;
+  UINTN                              DataLength;
+  BOOLEAN                            NeedRetry;  
+
+  Private   = GET_UFS_PEIM_HC_PRIVATE_DATA_FROM_THIS (This);
+  NeedRetry = TRUE;
+
+  if (DeviceIndex >= UFS_PEIM_MAX_LUNS) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if ((Private->Luns.BitMask & (BIT0 << DeviceIndex)) == 0) {
+    return EFI_ACCESS_DENIED;
+  }
+
+  ZeroMem (&SenseData, sizeof (SenseData));
+  ZeroMem (&Capacity, sizeof (Capacity));
+  ZeroMem (&Capacity16, sizeof (Capacity16));
+  SenseDataLength = sizeof (SenseData);
+  //
+  // First test unit ready
+  //
+  do {
+    Status = UfsPeimTestUnitReady (
+               Private,
+               DeviceIndex,
+               &SenseData,
+               &SenseDataLength
+               );
+    if (!EFI_ERROR (Status)) {
+      break;
+    }
+  
+    if (SenseDataLength == 0) {
+      continue;
+    }
+
+    Status = UfsPeimParsingSenseKeys (&(Private->Media[DeviceIndex]), 
&SenseData, &NeedRetry);
+    if (EFI_ERROR (Status)) {
+      return EFI_DEVICE_ERROR;
+    }
+
+  } while (NeedRetry);
+
+  DataLength      = sizeof (EFI_SCSI_DISK_CAPACITY_DATA);
+  SenseDataLength = 0;
+  Status = UfsPeimReadCapacity (Private, DeviceIndex, &Capacity, (UINT32 
*)&DataLength, NULL, &SenseDataLength);
+  if (EFI_ERROR (Status)) {
+    return EFI_DEVICE_ERROR;
+  }
+
+  if ((Capacity.LastLba3 == 0xff) && (Capacity.LastLba2 == 0xff) &&
+      (Capacity.LastLba1 == 0xff) && (Capacity.LastLba0 == 0xff)) {
+    DataLength      = sizeof (EFI_SCSI_DISK_CAPACITY_DATA16);
+    SenseDataLength = 0;
+    Status = UfsPeimReadCapacity16 (Private, DeviceIndex, &Capacity16, (UINT32 
*)&DataLength, NULL, &SenseDataLength);
+    if (EFI_ERROR (Status)) {
+      return EFI_DEVICE_ERROR;
+    }
+    MediaInfo->LastBlock  = (Capacity16.LastLba3 << 24) | (Capacity16.LastLba2 
<< 16) | (Capacity16.LastLba1 << 8) | Capacity16.LastLba0;

@@ Diff output truncated at 100000 characters. @@

------------------------------------------------------------------------------
One dashboard for servers and applications across Physical-Virtual-Cloud 
Widest out-of-the-box monitoring support with 50+ applications
Performance metrics, stats and reports that give you Actionable Insights
Deep dive visibility with transaction tracing using APM Insight.
http://ad.doubleclick.net/ddm/clk/290420510;117567292;y
_______________________________________________
edk2-commits mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/edk2-commits

Reply via email to