Add SmartCardReader specific files. These files have been written
specifically for UEFI.

This provides an implementation of the "Smart Card Reader Protocol" or
EFI_SMART_CARD_READER_PROTOCOL as described in "Unified Extensible
Firmware Interface Specification", version 2.5, April 2015, chapter
"35.6.1 Smart Card Reader Protocol".

The code heavily reuse an existing CCID driver from the CCID project
http://pcsclite.alioth.debian.org/ccid.html

CCID and ICCD are a protocols defined by the USB working group. All
modern USB smart card readers use CCID (or its variation ICCD for tokens).

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Ludovic Rousseau <ludovic.rouss...@gmail.com>
---
 MdeModulePkg/Library/SmartCardReader/CcidDriver.c  | 819 +++++++++++++++++++++
 MdeModulePkg/Library/SmartCardReader/CcidDriver.h  | 154 ++++
 .../Library/SmartCardReader/ComponentName.c        | 198 +++++
 .../Library/SmartCardReader/ComponentName.h        | 128 ++++
 .../Library/SmartCardReader/DriverBinding.h        | 211 ++++++
 MdeModulePkg/Library/SmartCardReader/License.txt   |  87 +++
 .../Library/SmartCardReader/SmartCardReader.inf    |  97 +++
 .../Library/SmartCardReader/SmartCardReader_impl.c | 453 ++++++++++++
 .../Library/SmartCardReader/SmartCardReader_impl.h |  94 +++
 MdeModulePkg/Library/SmartCardReader/config.h      |  64 ++
 MdeModulePkg/Library/SmartCardReader/debug.c       |  62 ++
 MdeModulePkg/Library/SmartCardReader/debuglog.h    |  81 ++
 12 files changed, 2448 insertions(+)
 create mode 100644 MdeModulePkg/Library/SmartCardReader/CcidDriver.c
 create mode 100644 MdeModulePkg/Library/SmartCardReader/CcidDriver.h
 create mode 100644 MdeModulePkg/Library/SmartCardReader/ComponentName.c
 create mode 100644 MdeModulePkg/Library/SmartCardReader/ComponentName.h
 create mode 100644 MdeModulePkg/Library/SmartCardReader/DriverBinding.h
 create mode 100644 MdeModulePkg/Library/SmartCardReader/License.txt
 create mode 100644 MdeModulePkg/Library/SmartCardReader/SmartCardReader.inf
 create mode 100644 MdeModulePkg/Library/SmartCardReader/SmartCardReader_impl.c
 create mode 100644 MdeModulePkg/Library/SmartCardReader/SmartCardReader_impl.h
 create mode 100644 MdeModulePkg/Library/SmartCardReader/config.h
 create mode 100644 MdeModulePkg/Library/SmartCardReader/debug.c
 create mode 100644 MdeModulePkg/Library/SmartCardReader/debuglog.h

diff --git a/MdeModulePkg/Library/SmartCardReader/CcidDriver.c 
b/MdeModulePkg/Library/SmartCardReader/CcidDriver.c
new file mode 100644
index 0000000..9c60211
--- /dev/null
+++ b/MdeModulePkg/Library/SmartCardReader/CcidDriver.c
@@ -0,0 +1,819 @@
+/*
+Copyright (c) 2014, Gemalto. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in
+  the documentation and/or other materials provided with the
+  distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/** @file
+  Entry points for the UEFI CCID driver
+
+  When a USB CCID device is inserted or removed then Start or Stop
+  functions from this file are called.
+
+**/
+
+#include <Library/PrintLib.h>
+#include <Protocol/SmartCardReader.h>
+
+#include "CcidDriver.h"
+#include "SmartCardReader_impl.h"
+
+#include "ifdhandler.h"
+#include "debuglog.h"
+#include "defs.h"
+#include "utils.h"
+#include "ccid_ifdhandler.h"
+#include "ccid.h"
+#include "ccid_uefi.h"
+
+static int Lun = 0;
+
+///
+/// Driver Binding Protocol instance
+///
+EFI_DRIVER_BINDING_PROTOCOL gSmartCardReaderDriverBinding = {
+  SmartCardReaderDriverBindingSupported,
+  SmartCardReaderDriverBindingStart,
+  SmartCardReaderDriverBindingStop,
+  CCID_DRIVER_VERSION,
+  NULL,
+  NULL
+};
+
+
+/**
+  Unloads an image.
+
+  @param  ImageHandle           Handle that identifies the image to be 
unloaded.
+
+  @retval EFI_SUCCESS           The image has been unloaded.
+  @retval EFI_INVALID_PARAMETER ImageHandle is not a valid image handle.
+
+**/
+EFI_STATUS
+EFIAPI
+SmartCardReaderUnload (
+  IN EFI_HANDLE  ImageHandle
+  )
+{
+  EFI_STATUS  Status;
+
+  EFI_HANDLE  *HandleBuffer;
+  UINTN       HandleCount;
+  UINTN       Index;
+
+  Log0(PCSC_LOG_DEBUG);
+
+  Status = EFI_SUCCESS;
+
+  //
+  // Retrieve array of all handles in the handle database
+  //
+  Status = gBS->LocateHandleBuffer (
+    AllHandles,
+    NULL,
+    NULL,
+    &HandleCount,
+    &HandleBuffer
+    );
+  if (EFI_ERROR (Status)) {
+    Log2(PCSC_LOG_DEBUG, "LocateHandleBuffer %d", Status);
+    return Status;
+  }
+
+  //
+  // Disconnect the current driver from handles in the handle database
+  //
+  for (Index = 0; Index < HandleCount; Index++) {
+    Status = gBS->DisconnectController (HandleBuffer[Index], gImageHandle, 
NULL);
+  }
+
+  //
+  // Free the array of handles
+  //
+  FreePool (HandleBuffer);
+
+  //
+  // Uninstall protocols installed in the driver entry point
+  //
+  Status = gBS->UninstallMultipleProtocolInterfaces (
+    ImageHandle,
+    &gEfiDriverBindingProtocolGuid,  &gSmartCardReaderDriverBinding,
+    &gEfiComponentNameProtocolGuid,  &gSmartCardReaderComponentName,
+    &gEfiComponentName2ProtocolGuid, &gSmartCardReaderComponentName2,
+    NULL
+    );
+  if (EFI_ERROR (Status)) {
+    Log2(PCSC_LOG_DEBUG, "UninstallMultipleProtocolInterfaces %d", Status);
+    return Status;
+  }
+
+
+  //
+  // Do any additional cleanup that is required for this driver
+  //
+
+  return EFI_SUCCESS;
+}
+
+/**
+  This is the declaration of an EFI image entry point. This entry point is
+  the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including
+  both device drivers and bus drivers.
+
+  @param  ImageHandle           The firmware allocated handle for the UEFI 
image.
+  @param  SystemTable           A pointer to the EFI System Table.
+
+  @retval EFI_SUCCESS           The operation completed successfully.
+  @retval Others                An unexpected error occurred.
+**/
+EFI_STATUS
+EFIAPI
+SmartCardReaderDriverEntryPoint (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  )
+{
+  EFI_STATUS  Status;
+
+  Status = EFI_SUCCESS;
+
+  // Install UEFI Driver Model protocol(s).
+  //
+  Status = EfiLibInstallAllDriverProtocols2 (
+    ImageHandle,
+    SystemTable,
+    &gSmartCardReaderDriverBinding,
+    ImageHandle,
+    &gSmartCardReaderComponentName,
+    &gSmartCardReaderComponentName2,
+    NULL,
+    NULL,
+    NULL,
+    NULL
+    );
+  ASSERT_EFI_ERROR (Status);
+
+  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().  Because 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
+SmartCardReaderDriverBindingSupported (
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
+  IN EFI_HANDLE                   ControllerHandle,
+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL
+  )
+{
+  EFI_STATUS          Status;
+  EFI_USB_IO_PROTOCOL *UsbIo;
+
+  Status = gBS->OpenProtocol (
+    ControllerHandle,
+    &gEfiUsbIoProtocolGuid,
+    (VOID **) &UsbIo,
+    This->DriverBindingHandle,
+    ControllerHandle,
+    EFI_OPEN_PROTOCOL_BY_DRIVER
+    );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Use the USB I/O Protocol interface to check whether Controller is
+  // a CCID device that can be managed by this driver.
+  //
+  Status = EFI_UNSUPPORTED;
+  if (IsUsbCcid (UsbIo)) {
+    Status = EFI_SUCCESS;
+  }
+
+  gBS->CloseProtocol (
+    ControllerHandle,
+    &gEfiUsbIoProtocolGuid,
+    This->DriverBindingHandle,
+    ControllerHandle
+    );
+
+  return Status;
+}
+
+/**
+  Initialize the USB CCID device.
+
+  @param  UsbCcidDev            Device instance to be initialized.
+
+  @retval EFI_SUCCESS           USB CCID device successfully initialized..
+  @retval Other                 USB CCID device was not initialized
+                                successfully.
+
+**/
+EFI_STATUS
+FinalizeUsbCcidDevice (
+  IN OUT USB_CCID_DEV *UsbCcidDev
+  )
+{
+  EFI_STATUS status = EFI_SUCCESS;
+  Log0(PCSC_LOG_DEBUG);
+
+  if (IFD_SUCCESS != IFDHCloseChannel(UsbCcidDev->Lun)) {
+    status = EFI_UNSUPPORTED;
+  }
+
+  return status;
+}
+
+/**
+  Initialize the USB CCID device.
+
+  @param  UsbCcidDev            Device instance to be initialized.
+
+  @retval EFI_SUCCESS           USB CCID device successfully initialized..
+  @retval Other                 USB CCID device was not initialized
+                                successfully.
+
+**/
+EFI_STATUS
+InitializeUsbCcidDevice (
+  IN OUT USB_CCID_DEV *UsbCcidDevice
+  )
+{
+  EFI_USB_IO_PROTOCOL *UsbIo;
+  EFI_STATUS Status;
+  CHAR16 *ManufacturerString = NULL;
+  CHAR16 *ProductString = NULL;
+  UINT16 *LangIDTable;
+  UINT16 TableSize;
+  INTN Index;
+  CHAR16 TxtLun[10];
+  INTN reader_index;
+  CcidDesc *ccid_slot;
+
+  Log0(PCSC_LOG_DEBUG);
+
+  if (IFD_SUCCESS != IFDHCreateChannel(Lun, (DWORD)UsbCcidDevice)) {
+    return EFI_UNSUPPORTED;
+  }
+
+  UsbCcidDevice->Lun = Lun;
+  UsbCcidDevice->State = SCARD_UNKNOWN;
+  UsbCcidDevice->AtrLength = 0;
+  UsbCcidDevice->InUse = 0;
+  UsbCcidDevice->CardProtocol = -1;
+
+  /* Lun are not recycled */
+  Lun++;
+
+  UsbIo = UsbCcidDevice->UsbIo;
+
+  //
+  // Get all supported languages.
+  //
+  TableSize = 0;
+  LangIDTable = NULL;
+  Status = UsbIo->UsbGetSupportedLanguages(UsbIo, &LangIDTable, &TableSize);
+  if (EFI_ERROR(Status)) {
+    Log1(PCSC_LOG_ERROR, "UsbGetSupportedLanguages");
+    goto error;
+  }
+
+  /* Get Manufacturer string */
+  for (Index = 0; Index < TableSize / sizeof (LangIDTable[0]); Index++) {
+    ManufacturerString = NULL;
+    Status = UsbIo->UsbGetStringDescriptor(UsbIo,
+        LangIDTable[Index],
+        UsbCcidDevice->DeviceDescriptor.StrManufacturer,
+        &ManufacturerString);
+
+    if (EFI_ERROR (Status) || (ManufacturerString == NULL)) {
+      continue;
+    }
+
+    StrCpy(UsbCcidDevice->ReaderName, ManufacturerString);
+    StrCat(UsbCcidDevice->ReaderName, L" ");
+
+    FreePool(ManufacturerString);
+    break;
+  }
+
+  /* Get Product string */
+  for (Index = 0; Index < TableSize / sizeof (LangIDTable[0]); Index++) {
+    ProductString = NULL;
+    Status = UsbIo->UsbGetStringDescriptor(UsbIo,
+        LangIDTable[Index],
+        UsbCcidDevice->DeviceDescriptor.StrProduct,
+        &ProductString);
+
+    if (EFI_ERROR (Status) || (ProductString == NULL)) {
+      continue;
+    }
+
+    StrCat(UsbCcidDevice->ReaderName, ProductString);
+
+    FreePool(ProductString);
+    break;
+  }
+
+error:
+  /* Can't get the strings from the device */
+  if ((NULL == ManufacturerString) || (NULL == ProductString)) {
+    UnicodeSPrint(UsbCcidDevice->ReaderName,
+        sizeof(UsbCcidDevice->ReaderName)/sizeof(UsbCcidDevice->ReaderName[0]),
+        L"%04X:%04X",
+        UsbCcidDevice->DeviceDescriptor.IdVendor,
+        UsbCcidDevice->DeviceDescriptor.IdProduct);
+  }
+
+  /* Add the Lun */
+  UnicodeSPrint(TxtLun, sizeof(TxtLun)/sizeof(TxtLun[0]), L" %d", 
UsbCcidDevice->Lun);
+  StrCat(UsbCcidDevice->ReaderName, TxtLun);
+
+  /* Length (in bytes) including Null terminator */
+  UsbCcidDevice->ReaderNameLength = StrSize(UsbCcidDevice->ReaderName);
+
+  /* set the reader name to the lower level */
+  reader_index = LunToReaderIndex(UsbCcidDevice->Lun);
+  ccid_slot = get_ccid_slot(reader_index);
+  ccid_slot->readerName = UsbCcidDevice->ReaderName;
+
+  return EFI_SUCCESS;
+}
+
+/**
+  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
+SmartCardReaderDriverBindingStart (
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
+  IN EFI_HANDLE                   ControllerHandle,
+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL
+  )
+{
+  EFI_STATUS           Status;
+  EFI_USB_IO_PROTOCOL  *UsbIo;
+  USB_CCID_DEV         *UsbCcidDevice;
+  EFI_TPL              OldTpl;
+  EFI_SMART_CARD_READER_PROTOCOL SmartCardReaderProtocol = {
+    .SCardConnect = SCardConnect,
+    .SCardDisconnect = SCardDisconnect,
+    .SCardStatus = SCardStatus,
+    .SCardTransmit =SCardTransmit,
+    .SCardControl = SCardControl,
+    .SCardGetAttrib = SCardGetAttrib
+  };
+  INTN slot, reader_index;
+  CcidDesc *ccid_slot;
+  _ccid_descriptor *ccid_descriptor;
+  USB_CCID_DEV *previous_UsbCcidDevice;
+
+  Log0(PCSC_LOG_DEBUG);
+
+  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
+
+  //
+  // Open USB I/O Protocol
+  //
+  Status = gBS->OpenProtocol (
+    ControllerHandle,
+    &gEfiUsbIoProtocolGuid,
+    (VOID **) &UsbIo,
+    This->DriverBindingHandle,
+    ControllerHandle,
+    EFI_OPEN_PROTOCOL_BY_DRIVER
+    );
+  if (EFI_ERROR (Status)) {
+    Log2(PCSC_LOG_DEBUG, "OpenProtocol %d", Status);
+    goto ErrorExit1;
+  }
+
+  UsbCcidDevice = AllocateZeroPool (sizeof (USB_CCID_DEV));
+  ASSERT (UsbCcidDevice != NULL);
+
+  UsbCcidDevice->UsbIo     = UsbIo;
+  UsbCcidDevice->Signature = USB_CCID_DEV_SIGNATURE;
+  UsbCcidDevice->ControllerHandle = ControllerHandle;
+  UsbCcidDevice->DriverBindingHandle = This->DriverBindingHandle;
+
+  Status = InitializeUsbCcidDevice(UsbCcidDevice);
+  if (EFI_ERROR (Status)) {
+    goto ErrorExit;
+  }
+
+  /* set the protocol functions */
+  UsbCcidDevice->SmartCardReaderProtocol = SmartCardReaderProtocol;
+
+  Status = gBS->InstallProtocolInterface (
+    &ControllerHandle,
+    &gEfiSmartCardReaderProtocolGuid,
+    EFI_NATIVE_INTERFACE,
+    &UsbCcidDevice->SmartCardReaderProtocol
+    );
+
+  if (EFI_ERROR (Status)) {
+    Log2(PCSC_LOG_DEBUG, "InstallProtocolInterface %d", Status);
+    goto ErrorExit;
+  }
+
+  UsbCcidDevice->ControllerNameTable = NULL;
+  AddUnicodeString2 (
+    "eng",
+    gSmartCardReaderComponentName.SupportedLanguages,
+    &UsbCcidDevice->ControllerNameTable,
+    L"Generic CCID Reader",
+    TRUE
+    );
+  AddUnicodeString2 (
+    "en",
+    gSmartCardReaderComponentName2.SupportedLanguages,
+    &UsbCcidDevice->ControllerNameTable,
+    L"Generic CCID Reader",
+    FALSE
+    );
+
+  /* multi slot readers */
+  reader_index = LunToReaderIndex(UsbCcidDevice->Lun);
+  ccid_slot = get_ccid_slot(reader_index);
+  ccid_descriptor = get_ccid_descriptor(reader_index);
+  previous_UsbCcidDevice = UsbCcidDevice;
+
+  for (slot=1; slot <= ccid_descriptor->bMaxSlotIndex; slot++) {
+    USB_CCID_DEV *new_UsbCcidDevice;
+    EFI_HANDLE new_ControllerHandle = NULL;
+    int new_reader_index;
+    CHAR16 TxtSlot[10];
+
+    Log2(PCSC_LOG_DEBUG, "slot: %d", slot);
+
+    if (-1 == (new_reader_index = GetNewReaderIndex(Lun))) {
+      return EFI_DEVICE_ERROR;
+    }
+
+    new_UsbCcidDevice = AllocateZeroPool (sizeof (USB_CCID_DEV));
+    ASSERT (new_UsbCcidDevice != NULL);
+
+    /* Copy the USB device */
+    duplicate_usb_device(reader_index, new_reader_index);
+
+    /* copy the UEFI device */
+    *new_UsbCcidDevice = *UsbCcidDevice;
+    new_UsbCcidDevice->Lun = Lun;
+    new_UsbCcidDevice->SlotNumber = slot;
+
+    /* Add the slot number */
+    UnicodeSPrint(TxtSlot, sizeof(TxtSlot)/sizeof(TxtSlot[0]), L", %d", slot);
+    StrCat(new_UsbCcidDevice->ReaderName, TxtSlot);
+
+    /* Set the reader name to the lower level */
+    new_reader_index = LunToReaderIndex(new_UsbCcidDevice->Lun);
+    get_ccid_slot(new_reader_index)->readerName = 
new_UsbCcidDevice->ReaderName;
+
+    /* Set the slot number ta the lower level */
+    get_ccid_descriptor(new_reader_index)->bCurrentSlotIndex = slot;
+
+    /* New Lun for a new slot */
+    Lun++;
+
+    /* Chaining */
+    previous_UsbCcidDevice->NextSlot = new_UsbCcidDevice;
+    previous_UsbCcidDevice = new_UsbCcidDevice;
+
+    /* Create a new UEFI SmartCardReaderProtocol object */
+    Status = gBS->InstallProtocolInterface (
+      &new_ControllerHandle,
+      &gEfiSmartCardReaderProtocolGuid,
+      EFI_NATIVE_INTERFACE,
+      &new_UsbCcidDevice->SmartCardReaderProtocol
+      );
+
+    if (EFI_ERROR (Status)) {
+      Log2(PCSC_LOG_DEBUG, "InstallProtocolInterface %d", Status);
+      goto ErrorExit;
+    }
+
+    new_UsbCcidDevice->ControllerHandle = new_ControllerHandle;
+  }
+
+  gBS->RestoreTPL (OldTpl);
+
+  return EFI_SUCCESS;
+
+  //
+  // Error handler
+  //
+ErrorExit:
+  if (EFI_ERROR (Status)) {
+    gBS->CloseProtocol (
+      ControllerHandle,
+      &gEfiUsbIoProtocolGuid,
+      This->DriverBindingHandle,
+      ControllerHandle
+      );
+
+    FreePool (UsbCcidDevice);
+    UsbCcidDevice = NULL;
+  }
+
+ErrorExit1:
+  gBS->RestoreTPL (OldTpl);
+  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
+SmartCardReaderDriverBindingStop (
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
+  IN EFI_HANDLE                   ControllerHandle,
+  IN UINTN                        NumberOfChildren,
+  IN EFI_HANDLE                   *ChildHandleBuffer OPTIONAL
+  )
+{
+  EFI_STATUS                     Status;
+  USB_CCID_DEV                   *UsbCcidDevice;
+  EFI_SMART_CARD_READER_PROTOCOL *SmartCardReaderProtocol;
+
+  Log0(PCSC_LOG_DEBUG);
+
+  Status = gBS->OpenProtocol (
+    ControllerHandle,
+    &gEfiSmartCardReaderProtocolGuid,
+    (VOID **) &SmartCardReaderProtocol,
+    This->DriverBindingHandle,
+    ControllerHandle,
+    EFI_OPEN_PROTOCOL_GET_PROTOCOL
+    );
+
+  if (EFI_ERROR (Status)) {
+    return EFI_UNSUPPORTED;
+  }
+
+  UsbCcidDevice = USB_CCID_DEV_FROM_SMART_CARD_READER_PROTOCOL 
(SmartCardReaderProtocol);
+
+  gBS->CloseProtocol (
+    ControllerHandle,
+    &gEfiUsbIoProtocolGuid,
+    This->DriverBindingHandle,
+    ControllerHandle
+    );
+
+  //
+  // Free all resources.
+  //
+  if (UsbCcidDevice->ControllerNameTable != NULL) {
+    FreeUnicodeStringTable (UsbCcidDevice->ControllerNameTable);
+  }
+
+  /* For each slot */
+  while (UsbCcidDevice) {
+    USB_CCID_DEV *NextSlot;
+
+    Log2(PCSC_LOG_DEBUG, "Closing slot: %d", UsbCcidDevice->SlotNumber);
+
+    Status = FinalizeUsbCcidDevice(UsbCcidDevice);
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+
+    /* Remove the protocol Interface */
+    Status = gBS->UninstallProtocolInterface (
+      UsbCcidDevice->ControllerHandle,
+      &gEfiSmartCardReaderProtocolGuid,
+      &UsbCcidDevice->SmartCardReaderProtocol
+      );
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+
+    NextSlot = UsbCcidDevice->NextSlot;
+
+    /* Free allocated memory */
+    FreePool (UsbCcidDevice);
+
+    UsbCcidDevice = NextSlot;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Uses USB I/O to check whether the device is a USB CCID device.
+
+  @param  UsbIo    Pointer to a USB I/O protocol instance.
+
+  @retval TRUE     Device is a USB CCID device.
+  @retval FALSE    Device is a not USB CCID device.
+
+ **/
+BOOLEAN
+IsUsbCcid (
+  IN  EFI_USB_IO_PROTOCOL     *UsbIo
+  )
+{
+  EFI_STATUS                    Status;
+  EFI_USB_INTERFACE_DESCRIPTOR  InterfaceDescriptor;
+  EFI_USB_DEVICE_DESCRIPTOR DeviceDescriptor;
+
+  //
+  // Get the default interface descriptor
+  //
+  Status = UsbIo->UsbGetInterfaceDescriptor (
+    UsbIo,
+    &InterfaceDescriptor
+    );
+
+  if (EFI_ERROR (Status)) {
+    Log2(PCSC_LOG_DEBUG, "UsbGetInterfaceDescriptor %d", Status);
+    return FALSE;
+  }
+
+  Status = UsbIo->UsbGetDeviceDescriptor (
+    UsbIo,
+    &DeviceDescriptor);
+
+  if (EFI_ERROR (Status)) {
+    Log2(PCSC_LOG_DEBUG, "UsbGetDeviceDescriptor %d", Status);
+    return FALSE;
+  }
+
+  Log3(PCSC_LOG_DEBUG, "IdVendor: %04X, IdProduct: %04X",
+    DeviceDescriptor.IdVendor, DeviceDescriptor.IdProduct);
+
+  if (InterfaceDescriptor.InterfaceClass == CLASS_CCID) {
+    Log1(PCSC_LOG_DEBUG, "Found a CCID device!");
+
+    return TRUE;
+  }
+
+  /* Log1(PCSC_LOG_DEBUG, "Not a CCID device"); */
+  return FALSE;
+}
+
diff --git a/MdeModulePkg/Library/SmartCardReader/CcidDriver.h 
b/MdeModulePkg/Library/SmartCardReader/CcidDriver.h
new file mode 100644
index 0000000..14fade4
--- /dev/null
+++ b/MdeModulePkg/Library/SmartCardReader/CcidDriver.h
@@ -0,0 +1,154 @@
+/*
+Copyright (c) 2014, Gemalto. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in
+  the documentation and/or other materials provided with the
+  distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/** @file
+  TODO: Brief Description of UEFI Driver SmartCardReader
+
+  TODO: Detailed Description of UEFI Driver SmartCardReader
+
+**/
+
+#ifndef __EFI_CCID_DRIVER_H__
+#define __EFI_CCID_DRIVER_H__
+
+#include <Uefi.h>
+
+//
+// Libraries
+//
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/BaseLib.h>
+#include <Library/UefiLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/DebugLib.h>
+#include <Library/ReportStatusCodeLib.h>
+
+
+//
+// UEFI Driver Model Protocols
+//
+#include <Protocol/DriverBinding.h>
+#include <Protocol/ComponentName2.h>
+#include <Protocol/ComponentName.h>
+#include <Protocol/SmartCardReader.h>
+
+//
+// Consumed Protocols
+//
+#include <Protocol/UsbIo.h>
+
+
+//
+// Produced Protocols
+//
+
+
+//
+// Guids
+//
+
+//
+// Driver Version
+//
+#define CCID_DRIVER_VERSION  0x00000001
+
+#ifndef MAX_ATR_SIZE
+#define MAX_ATR_SIZE 33 /* from pcsclite.h */
+#endif
+
+//
+// Protocol instances
+//
+extern EFI_DRIVER_BINDING_PROTOCOL  gSmartCardReaderDriverBinding;
+extern EFI_COMPONENT_NAME2_PROTOCOL  gSmartCardReaderComponentName2;
+extern EFI_COMPONENT_NAME_PROTOCOL  gSmartCardReaderComponentName;
+
+
+//
+// Include files with function prototypes
+//
+#include "DriverBinding.h"
+#include "ComponentName.h"
+
+#define CLASS_CCID               11
+
+#define USB_CCID_DEV_SIGNATURE SIGNATURE_32 ('c', 'c', 'i', 'd')
+
+
+///
+/// Device instance of USB CCID device.
+///
+typedef struct _USB_CCID_DEV {
+  UINTN                         Signature;
+  EFI_DEVICE_PATH_PROTOCOL      *DevicePath;
+  EFI_EVENT                     DelayedRecoveryEvent;
+  EFI_USB_IO_PROTOCOL           *UsbIo;
+  EFI_HANDLE                    *ControllerHandle;
+  EFI_HANDLE                    *DriverBindingHandle;
+  EFI_SMART_CARD_READER_PROTOCOL SmartCardReaderProtocol;
+  EFI_USB_DEVICE_DESCRIPTOR     DeviceDescriptor;
+  EFI_USB_CONFIG_DESCRIPTOR     ConfigDescriptor;
+  EFI_USB_INTERFACE_DESCRIPTOR  InterfaceDescriptor;
+  EFI_UNICODE_STRING_TABLE      *ControllerNameTable;
+  INTN                          SlotNumber;
+  struct _USB_CCID_DEV          *NextSlot;
+  UINTN                         Lun;
+  CHAR16                        ReaderName[128];
+  INTN                          ReaderNameLength;
+  unsigned char                 Atr[MAX_ATR_SIZE];
+  INTN                          AtrLength;
+  INTN                          CardProtocol;
+  INTN                          State;
+  INTN                          InUse;
+} USB_CCID_DEV;
+
+#define USB_CCID_DEV_FROM_SMART_CARD_READER_PROTOCOL(a) \
+    CR(a, USB_CCID_DEV, SmartCardReaderProtocol, USB_CCID_DEV_SIGNATURE)
+
+
+//
+// Internal worker functions
+//
+
+/**
+  Uses USB I/O to check whether the device is a USB CCID device.
+
+  @param  UsbIo    Pointer to a USB I/O protocol instance.
+
+  @retval TRUE     Device is a USB CCID device.
+  @retval FALSE    Device is a not USB CCID device.
+
+**/
+BOOLEAN
+IsUsbCcid (
+  IN  EFI_USB_IO_PROTOCOL     *UsbIo
+  );
+
+#endif
diff --git a/MdeModulePkg/Library/SmartCardReader/ComponentName.c 
b/MdeModulePkg/Library/SmartCardReader/ComponentName.c
new file mode 100644
index 0000000..3927361
--- /dev/null
+++ b/MdeModulePkg/Library/SmartCardReader/ComponentName.c
@@ -0,0 +1,198 @@
+/*
+Copyright (c) 2014, Gemalto. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in
+  the documentation and/or other materials provided with the
+  distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+/** @file
+  TODO: Brief Description of UEFI Driver SmartCardReader
+
+  TODO: Detailed Description of UEFI Driver SmartCardReader
+
+**/
+
+#include "CcidDriver.h"
+
+///
+/// Component Name Protocol instance
+///
+GLOBAL_REMOVE_IF_UNREFERENCED
+EFI_COMPONENT_NAME_PROTOCOL  gSmartCardReaderComponentName = {
+  (EFI_COMPONENT_NAME_GET_DRIVER_NAME)    
SmartCardReaderComponentNameGetDriverName,
+  
(EFI_COMPONENT_NAME_GET_CONTROLLER_NAME)SmartCardReaderComponentNameGetControllerName,
+  "eng"
+};
+
+///
+/// Component Name 2 Protocol instance
+///
+GLOBAL_REMOVE_IF_UNREFERENCED
+EFI_COMPONENT_NAME2_PROTOCOL  gSmartCardReaderComponentName2 = {
+  SmartCardReaderComponentNameGetDriverName,
+  SmartCardReaderComponentNameGetControllerName,
+  "en"
+};
+
+///
+/// Table of driver names
+///
+GLOBAL_REMOVE_IF_UNREFERENCED
+EFI_UNICODE_STRING_TABLE mSmartCardReaderDriverNameTable[] = {
+  { "eng;en", (CHAR16 *)L"USB Smart Card Driver (CCID)" },
+  { NULL, NULL }
+};
+
+/**
+  Retrieves a Unicode string that is the user-readable name of the EFI Driver.
+
+  @param  This       A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+  @param  Language   A pointer to a three-character ISO 639-2 language
+                     identifier.  This is the language of the driver
+                     name that 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.
+  @param  DriverName 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
+SmartCardReaderComponentNameGetDriverName (
+  IN EFI_COMPONENT_NAME2_PROTOCOL  *This,
+  IN  CHAR8                        *Language,
+  OUT CHAR16                       **DriverName
+  )
+{
+  return LookupUnicodeString2 (
+    Language,
+    This->SupportedLanguages,
+    mSmartCardReaderDriverNameTable,
+    DriverName,
+    (BOOLEAN)(This != &gSmartCardReaderComponentName2)
+    );
+}
+
+/**
+  Retrieves a Unicode string that is the user readable name of the controller
+  that is being managed by an EFI Driver.
+
+  @param  This             A pointer to the EFI_COMPONENT_NAME_PROTOCOL
+                           instance.
+  @param  ControllerHandle 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      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         A pointer to a three character ISO 639-2
+                           language identifier.  This is the language of
+                           the controller 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.
+  @param  ControllerName   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
+SmartCardReaderComponentNameGetControllerName (
+  IN  EFI_COMPONENT_NAME2_PROTOCOL  *This,
+  IN  EFI_HANDLE                    ControllerHandle,
+  IN  EFI_HANDLE                    ChildHandle        OPTIONAL,
+  IN  CHAR8                         *Language,
+  OUT CHAR16                        **ControllerName
+  )
+{
+  EFI_STATUS  Status;
+
+  //
+  // ChildHandle must be NULL for a Device Driver
+  //
+  if (ChildHandle != NULL) {
+    return EFI_UNSUPPORTED;
+  }
+
+  //
+  // Make sure this driver is currently managing ControllerHandle
+  //
+  Status = EfiTestManagedDevice (
+    ControllerHandle,
+    gSmartCardReaderDriverBinding.DriverBindingHandle,
+    &gEfiUsbIoProtocolGuid
+    );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Lookup name of controller specified by ControllerHandle
+  //
+  Status = EFI_UNSUPPORTED;
+
+  return Status;
+}
diff --git a/MdeModulePkg/Library/SmartCardReader/ComponentName.h 
b/MdeModulePkg/Library/SmartCardReader/ComponentName.h
new file mode 100644
index 0000000..5102df5
--- /dev/null
+++ b/MdeModulePkg/Library/SmartCardReader/ComponentName.h
@@ -0,0 +1,128 @@
+/*
+Copyright (c) 2014, Gemalto. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in
+  the documentation and/or other materials provided with the
+  distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/** @file
+  TODO: Brief Description of UEFI Driver SmartCardReader
+
+  TODO: Detailed Description of UEFI Driver SmartCardReader
+
+**/
+
+/**
+  Retrieves a Unicode string that is the user-readable name of the EFI Driver.
+
+  @param  This       A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+  @param  Language   A pointer to a three-character ISO 639-2 language
+                     identifier.  This is the language of the driver
+                     name that 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.
+  @param  DriverName 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
+SmartCardReaderComponentNameGetDriverName (
+  IN     EFI_COMPONENT_NAME2_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 an EFI Driver.
+
+  @param  This             A pointer to the EFI_COMPONENT_NAME_PROTOCOL
+                           instance.
+  @param  ControllerHandle 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      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         A pointer to a three character ISO 639-2
+                           language identifier.  This is the language of
+                           the controller 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.
+  @param  ControllerName   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
+SmartCardReaderComponentNameGetControllerName (
+  IN     EFI_COMPONENT_NAME2_PROTOCOL  *This,
+  IN     EFI_HANDLE                    ControllerHandle,
+  IN     EFI_HANDLE                    ChildHandle        OPTIONAL,
+  IN     CHAR8                         *Language,
+     OUT CHAR16                        **ControllerName
+  );
diff --git a/MdeModulePkg/Library/SmartCardReader/DriverBinding.h 
b/MdeModulePkg/Library/SmartCardReader/DriverBinding.h
new file mode 100644
index 0000000..7eb55bd
--- /dev/null
+++ b/MdeModulePkg/Library/SmartCardReader/DriverBinding.h
@@ -0,0 +1,211 @@
+/*
+Copyright (c) 2014, Gemalto. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in
+  the documentation and/or other materials provided with the
+  distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/** @file
+  TODO: Brief Description of UEFI Driver SmartCardReader
+
+  TODO: Detailed Description of UEFI Driver SmartCardReader
+
+**/
+
+/**
+  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().  Because 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
+SmartCardReaderDriverBindingSupported (
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
+  IN EFI_HANDLE                   ControllerHandle,
+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL
+  );
+
+/**
+  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
+SmartCardReaderDriverBindingStart (
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
+  IN EFI_HANDLE                   ControllerHandle,
+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL
+  );
+
+/**
+  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
+SmartCardReaderDriverBindingStop (
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
+  IN  EFI_HANDLE                  ControllerHandle,
+  IN  UINTN                       NumberOfChildren,
+  IN  EFI_HANDLE                  *ChildHandleBuffer OPTIONAL
+  );
diff --git a/MdeModulePkg/Library/SmartCardReader/License.txt 
b/MdeModulePkg/Library/SmartCardReader/License.txt
new file mode 100644
index 0000000..328a934
--- /dev/null
+++ b/MdeModulePkg/Library/SmartCardReader/License.txt
@@ -0,0 +1,87 @@
+Copyright (c) 2014, Gemalto. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in
+  the documentation and/or other materials provided with the
+  distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+
+---
+
+Files reader.h, ifdhandler.h, misc.h, pcsclite.h and wintypes.h are from
+the pcsc-lite project http://pcsclite.alioth.debian.org/pcsclite.html
+and are copyrighted by:
+- Ludovic Rousseau <ludovic.rouss...@free.fr>
+- David Corcoran <corco...@musclecard.com>
+- Damien Sauveron <damien.sauve...@labri.fr>
+- Martin Paljak <mar...@paljak.pri.ee>
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+ 3. The name of the author may not be used to endorse or promote products
+    derived from this software without specific prior written permission.
+
+ Changes to this license can be made only by the copyright author with
+ explicit written consent.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+---
+
+Files in directory libccid/ are from the CCID project
+http://pcsclite.alioth.debian.org/ccid.html and are copyrighted by:
+- Ludovic Rousseau <ludovic.rouss...@free.fr>
+- Olaf Kirch <o...@suse.de>
+- Andreas Jellinghaus <a...@dungeon.inka.de>
+- Matthias Bruestle
+- Carlos Prados <cpra...@yahoo.com>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
diff --git a/MdeModulePkg/Library/SmartCardReader/SmartCardReader.inf 
b/MdeModulePkg/Library/SmartCardReader/SmartCardReader.inf
new file mode 100644
index 0000000..6912f64
--- /dev/null
+++ b/MdeModulePkg/Library/SmartCardReader/SmartCardReader.inf
@@ -0,0 +1,97 @@
+# Copyright (c) 2014, Gemalto. All rights reserved.
+# 
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 
+# * Redistributions of source code must retain the above copyright
+#   notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+#   notice, this list of conditions and the following disclaimer in
+#   the documentation and/or other materials provided with the
+#   distribution.
+# 
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+
+## @file
+#  TODO: Brief Description of UEFI Driver SmartCardReader
+#
+#  TODO: Detailed Description of UEFI Driver SmartCardReader
+#
+##
+
+[Defines]
+  INF_VERSION               = 0x00010005
+  BASE_NAME                 = SmartCardReader
+  FILE_GUID                 = bb902a5e-f073-11e3-9373-5cf9dd714e6f
+  MODULE_TYPE               = UEFI_DRIVER
+
+  VERSION_STRING            = 1.0
+  ENTRY_POINT               = SmartCardReaderDriverEntryPoint
+  UNLOAD_IMAGE              = SmartCardReaderUnload
+
+
+[Packages]
+  MdePkg/MdePkg.dec
+
+[Sources]
+  CcidDriver.h
+  CcidDriver.c
+  ComponentName.c
+  ComponentName.h
+  debug.c
+  SmartCardReader_impl.c
+  SmartCardReader_impl.h
+  libccid/ccid.c
+  libccid/ccid.h
+  libccid/ccid_uefi.c
+  libccid/ccid_uefi.h
+  libccid/ccid_uefi.h
+  libccid/commands.c
+  libccid/commands.h
+  libccid/ifdhandler.c
+  libccid/openct/buffer.c
+  libccid/openct/buffer.h
+  libccid/openct/checksum.c
+  libccid/openct/checksum.h
+  libccid/openct/proto-t1.c
+  libccid/openct/proto-t1.h
+  libccid/towitoko/atr.c
+  libccid/towitoko/atr.h
+  libccid/towitoko/pps.c
+  libccid/towitoko/pps.h
+  libccid/utils.c
+  libccid/utils.h
+
+
+[LibraryClasses]
+  UefiDriverEntryPoint
+  UefiBootServicesTableLib
+  MemoryAllocationLib
+  BaseMemoryLib
+  BaseLib
+  UefiLib
+  DevicePathLib
+  DebugLib
+
+
+[Protocols]
+  gEfiDriverBindingProtocolGuid
+  gEfiUsbIoProtocolGuid
+  gEfiComponentName2ProtocolGuid
+  gEfiComponentNameProtocolGuid
+  gEfiSmartCardReaderProtocolGuid
+
+[Guids]
+
diff --git a/MdeModulePkg/Library/SmartCardReader/SmartCardReader_impl.c 
b/MdeModulePkg/Library/SmartCardReader/SmartCardReader_impl.c
new file mode 100644
index 0000000..4387128
--- /dev/null
+++ b/MdeModulePkg/Library/SmartCardReader/SmartCardReader_impl.c
@@ -0,0 +1,453 @@
+/*
+Copyright (c) 2014, Gemalto. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in
+  the documentation and/or other materials provided with the
+  distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "CcidDriver.h"
+#include "SmartCardReader_impl.h"
+#include <Protocol/SmartCardReader.h>
+
+#include "debuglog.h"
+#include "ifdhandler.h"
+#include "utils.h"
+#include "commands.h"
+#include "ccid.h"
+#include "atr.h"
+#include "defs.h"
+
+#define CheckThis if (NULL == This) return EFI_INVALID_PARAMETER
+
+static
+void
+update_state(
+  USB_CCID_DEV *UsbCcidDevice
+  )
+{
+  INTN reader_index;
+  RESPONSECODE response;
+  unsigned char pcbuffer[SIZE_GET_SLOT_STATUS];
+
+  UsbCcidDevice->State = SCARD_UNKNOWN;
+
+  if (-1 == (reader_index = LunToReaderIndex(UsbCcidDevice->Lun))) {
+    return;
+  }
+
+  response = CmdGetSlotStatus(reader_index, pcbuffer);
+
+  if (response != IFD_SUCCESS) {
+    return;
+  }
+
+  switch (pcbuffer[7] & CCID_ICC_STATUS_MASK) { /* bStatus */
+    case CCID_ICC_PRESENT_ACTIVE:
+      UsbCcidDevice->State = SCARD_ACTIVE;
+      break;
+    case CCID_ICC_PRESENT_INACTIVE:
+      UsbCcidDevice->State = SCARD_INACTIVE;
+      UsbCcidDevice->AtrLength = 0;
+      break;
+    case CCID_ICC_ABSENT:
+      UsbCcidDevice->State = SCARD_ABSENT;
+      UsbCcidDevice->AtrLength = 0;
+      break;
+  }
+}
+
+EFI_STATUS
+EFIAPI
+SCardConnect (
+  IN     EFI_SMART_CARD_READER_PROTOCOL *This,
+  IN     UINT32                         AccessMode,
+  IN     UINT32                         CardAction,
+  IN     UINT32                         PreferredProtocols,
+     OUT UINT32                         *ActiveProtocol
+  )
+{
+  EFI_STATUS Status = EFI_SUCCESS;
+  RESPONSECODE response;
+  USB_CCID_DEV *UsbCcidDevice;
+  int protocol, availableProtocols;
+  ATR_t atr;
+
+  Log0(PCSC_LOG_DEBUG);
+
+  /* Check parameters */
+  CheckThis;
+
+  /* Invalid card actions */
+  if ((SCARD_CA_UNPOWER == CardAction) || (SCARD_CA_EJECT == CardAction)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  UsbCcidDevice = USB_CCID_DEV_FROM_SMART_CARD_READER_PROTOCOL (This);
+
+  /* Already used by another SCardConnect */
+  if (UsbCcidDevice->InUse) {
+    return EFI_ACCESS_DENIED;
+  }
+
+  UsbCcidDevice->InUse = 1;
+
+  /* Access the reader: nothing to do */
+  if (SCARD_AM_READER == AccessMode) {
+    return EFI_SUCCESS;
+  }
+
+  if (AccessMode != SCARD_AM_CARD) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  /* Perform the CardAction action */
+  Status = SCardDisconnect(This, CardAction);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  /* No ATR so no protocol to negociate */
+  *ActiveProtocol = SCARD_PROTOCOL_UNDEFINED;
+  if (0 == UsbCcidDevice->AtrLength) {
+    return EFI_SUCCESS;
+  }
+
+  if (ATR_OK != ATR_InitFromArray(&atr, UsbCcidDevice->Atr, 
UsbCcidDevice->AtrLength)) {
+    return EFI_DEVICE_ERROR;
+  }
+
+  if (ATR_OK != ATR_GetDefaultProtocol(&atr, &protocol, &availableProtocols)) {
+    return EFI_DEVICE_ERROR;
+  }
+
+  if ((PreferredProtocols & SCARD_PROTOCOL_T1)
+      && (availableProtocols & 1 << 1)) {
+    *ActiveProtocol = SCARD_PROTOCOL_T1;
+    protocol = SCARD_PROTOCOL_T1;
+  }
+  else
+    if ((PreferredProtocols & SCARD_PROTOCOL_T0)
+        && (availableProtocols & 1 << 0)) {
+      *ActiveProtocol = SCARD_PROTOCOL_T0;
+      protocol = SCARD_PROTOCOL_T0;
+    }
+    else {
+      return EFI_UNSUPPORTED;
+    }
+
+  switch (protocol) {
+    case SCARD_PROTOCOL_T0:
+      UsbCcidDevice->CardProtocol = T_0;
+      break;
+    case SCARD_PROTOCOL_T1:
+      UsbCcidDevice->CardProtocol = T_1;
+      break;
+  }
+  response = IFDHSetProtocolParameters(UsbCcidDevice->Lun, protocol, 0, 0, 0, 
0);
+  if (response != IFD_SUCCESS) {
+    Status = EFI_UNSUPPORTED;
+  }
+
+  return Status;
+}
+
+EFI_STATUS
+EFIAPI
+SCardDisconnect (
+  IN EFI_SMART_CARD_READER_PROTOCOL *This,
+  IN UINT32                         CardAction
+  )
+{
+  EFI_STATUS Status = EFI_SUCCESS;
+  USB_CCID_DEV *UsbCcidDevice;
+  RESPONSECODE response;
+  DWORD length;
+
+  Log0(PCSC_LOG_DEBUG);
+
+  /* Check parameters */
+  CheckThis;
+
+  UsbCcidDevice = USB_CCID_DEV_FROM_SMART_CARD_READER_PROTOCOL (This);
+
+  UsbCcidDevice->InUse = 0;
+
+  switch (CardAction) {
+    case SCARD_CA_EJECT:
+      Status = EFI_UNSUPPORTED;
+      UsbCcidDevice->InUse = 1; /* do not release the reader. See spec */
+      break;
+
+    case SCARD_CA_NORESET:
+      break;
+
+    case SCARD_CA_COLDRESET:
+      /* Power Off */
+      response = IFDHPowerICC(UsbCcidDevice->Lun, IFD_POWER_DOWN,
+          UsbCcidDevice->Atr, &length);
+      if (response != IFD_SUCCESS) {
+        Status = EFI_DEVICE_ERROR;
+        break;
+      }
+
+      /* Power On */
+      response = IFDHPowerICC(UsbCcidDevice->Lun, IFD_POWER_UP,
+          UsbCcidDevice->Atr, &length);
+      if (response != IFD_SUCCESS) {
+        Status = EFI_NOT_READY;
+      }
+
+      UsbCcidDevice->AtrLength = length;
+      break;
+
+    case SCARD_CA_WARMRESET:
+      /* Reset */
+      response = IFDHPowerICC(UsbCcidDevice->Lun, IFD_RESET,
+          UsbCcidDevice->Atr, &length);
+      if (response != IFD_SUCCESS) {
+        Status = EFI_DEVICE_ERROR;
+      }
+
+      UsbCcidDevice->AtrLength = length;
+      break;
+
+    case SCARD_CA_UNPOWER:
+      /* Power Off */
+      response = IFDHPowerICC(UsbCcidDevice->Lun, IFD_POWER_DOWN,
+          UsbCcidDevice->Atr, &length);
+      if (response != IFD_SUCCESS) {
+        Status = EFI_DEVICE_ERROR;
+      }
+
+      UsbCcidDevice->AtrLength = 0;
+      break;
+
+    default:
+      Status = EFI_INVALID_PARAMETER;
+  }
+
+  return Status;
+}
+
+EFI_STATUS
+EFIAPI
+SCardStatus (
+  IN     EFI_SMART_CARD_READER_PROTOCOL *This,
+     OUT CHAR16                         *ReaderName,
+  IN OUT UINTN                          *ReaderNameLength,
+     OUT UINT32                         *State,
+     OUT UINT32                         *CardProtocol,
+     OUT UINT8                          *Atr,
+  IN OUT UINTN                          *AtrLength
+  )
+{
+  USB_CCID_DEV *UsbCcidDevice;
+  UINTN old_AtrLength = 0, old_ReaderNameLength = 0;
+
+  Log0(PCSC_LOG_DEBUG);
+
+  /* Check parameters */
+  CheckThis;
+  if ((NULL == ReaderNameLength) && (NULL != ReaderName)) {
+    return EFI_INVALID_PARAMETER;
+  }
+  if ((NULL == AtrLength) && (NULL != Atr)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  UsbCcidDevice = USB_CCID_DEV_FROM_SMART_CARD_READER_PROTOCOL (This);
+
+  update_state(UsbCcidDevice);
+
+  if (State) {
+    *State = UsbCcidDevice->State;
+  }
+  if (CardProtocol) {
+    *CardProtocol = UsbCcidDevice->CardProtocol;
+  }
+
+  if (AtrLength) {
+    old_AtrLength = *AtrLength;
+    *AtrLength = UsbCcidDevice->AtrLength;
+  }
+  if (old_AtrLength < UsbCcidDevice->AtrLength) {
+    return EFI_BUFFER_TOO_SMALL;
+  }
+
+  if (Atr) {
+    CopyMem(Atr, UsbCcidDevice->Atr, UsbCcidDevice->AtrLength);
+  }
+
+  if (ReaderNameLength) {
+    old_ReaderNameLength = *ReaderNameLength;
+    *ReaderNameLength = UsbCcidDevice->ReaderNameLength;
+  }
+  if (old_ReaderNameLength < UsbCcidDevice->ReaderNameLength) {
+    return EFI_BUFFER_TOO_SMALL;
+  }
+
+  if (ReaderName) {
+    CopyMem(ReaderName, UsbCcidDevice->ReaderName, 
UsbCcidDevice->ReaderNameLength);
+  }
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+SCardTransmit (
+  IN     EFI_SMART_CARD_READER_PROTOCOL *This,
+  IN     UINT8                          *CAPDU,
+  IN     UINTN                          CAPDULength,
+     OUT UINT8                          *RAPDU,
+  IN OUT UINTN                          *RAPDULength
+  )
+{
+  USB_CCID_DEV *UsbCcidDevice;
+  RESPONSECODE response;
+  SCARD_IO_HEADER SendPci;
+  DWORD RxLength;
+  EFI_STATUS Status = EFI_SUCCESS;
+  unsigned char RxBuffer[MAX_BUFFER_SIZE_EXTENDED];
+
+  Log0(PCSC_LOG_DEBUG);
+
+  /* Check parameters */
+  CheckThis;
+  if ((NULL == CAPDU) || (0 == CAPDULength)
+      || (NULL == RAPDU) || (NULL == RAPDULength)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  UsbCcidDevice = USB_CCID_DEV_FROM_SMART_CARD_READER_PROTOCOL (This);
+
+  /* Check the card is present and powered */
+  update_state(UsbCcidDevice);
+  if (UsbCcidDevice->State != SCARD_ACTIVE) {
+    return EFI_NOT_READY;
+  }
+
+  RxLength = sizeof RxBuffer;
+  SendPci.Protocol = UsbCcidDevice->CardProtocol;
+  response = IFDHTransmitToICC(UsbCcidDevice->Lun, SendPci, CAPDU, 
CAPDULength, RxBuffer, &RxLength, NULL);
+  if (*RAPDULength < RxLength) {
+    Status = EFI_BUFFER_TOO_SMALL;
+  }
+  *RAPDULength = RxLength;
+
+  if (IFD_SUCCESS != response) {
+    Status = EFI_DEVICE_ERROR;
+  }
+  else {
+    CopyMem(RAPDU, RxBuffer, RxLength);
+  }
+
+  return Status;
+}
+
+EFI_STATUS
+EFIAPI
+SCardControl (
+  IN     EFI_SMART_CARD_READER_PROTOCOL *This,
+  IN     UINT32                         ControlCode,
+  IN     UINT8                          *InBuffer,
+  IN     UINTN                          InBufferLength,
+     OUT UINT8                          *OutBuffer,
+  IN OUT UINTN                          *OutBufferLength
+  )
+{
+  USB_CCID_DEV *UsbCcidDevice;
+  RESPONSECODE response;
+  DWORD dwBytesReturned;
+  UINTN dummy = 0;
+
+  Log0(PCSC_LOG_DEBUG);
+
+  /* Check parameters */
+  CheckThis;
+  if ((NULL == OutBuffer) && (NULL != OutBufferLength)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  UsbCcidDevice = USB_CCID_DEV_FROM_SMART_CARD_READER_PROTOCOL (This);
+
+  /* OutBufferLength may be NULL */
+  if (NULL == OutBufferLength) {
+    OutBufferLength = &dummy;
+  }
+
+  dwBytesReturned = *OutBufferLength;
+  response = IFDHControl(UsbCcidDevice->Lun, ControlCode, InBuffer, 
InBufferLength, OutBuffer, *OutBufferLength, &dwBytesReturned);
+  *OutBufferLength = dwBytesReturned;
+
+  switch (response) {
+    case IFD_SUCCESS:
+      return EFI_SUCCESS;
+    case IFD_ERROR_NOT_SUPPORTED:
+      return EFI_UNSUPPORTED;
+    case IFD_ERROR_INSUFFICIENT_BUFFER:
+      return EFI_BUFFER_TOO_SMALL;
+    default:
+      return EFI_DEVICE_ERROR;
+  }
+}
+
+EFI_STATUS
+EFIAPI
+SCardGetAttrib (
+  IN     EFI_SMART_CARD_READER_PROTOCOL *This,
+  IN     UINT32                         Attrib,
+     OUT UINT8                          *OutBuffer,
+  IN OUT UINTN                          *OutBufferLength
+  )
+{
+  USB_CCID_DEV *UsbCcidDevice;
+  RESPONSECODE response;
+  DWORD dwBytesReturned;
+
+  Log0(PCSC_LOG_DEBUG);
+
+  /* Check parameters */
+  CheckThis;
+  if ((NULL == OutBuffer) || (NULL == OutBufferLength) || (0 == 
*OutBufferLength)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  UsbCcidDevice = USB_CCID_DEV_FROM_SMART_CARD_READER_PROTOCOL (This);
+  dwBytesReturned = *OutBufferLength;
+  response = IFDHGetCapabilities(UsbCcidDevice->Lun, Attrib, &dwBytesReturned, 
OutBuffer);
+  *OutBufferLength = dwBytesReturned;
+
+  switch (response) {
+    case IFD_SUCCESS:
+      return EFI_SUCCESS;
+    case IFD_ERROR_TAG:
+      return EFI_UNSUPPORTED;
+    case IFD_ERROR_INSUFFICIENT_BUFFER:
+      return EFI_BUFFER_TOO_SMALL;
+    default:
+      return EFI_DEVICE_ERROR;
+  }
+}
+
diff --git a/MdeModulePkg/Library/SmartCardReader/SmartCardReader_impl.h 
b/MdeModulePkg/Library/SmartCardReader/SmartCardReader_impl.h
new file mode 100644
index 0000000..989a185
--- /dev/null
+++ b/MdeModulePkg/Library/SmartCardReader/SmartCardReader_impl.h
@@ -0,0 +1,94 @@
+/*
+Copyright (c) 2014, Gemalto. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in
+  the documentation and/or other materials provided with the
+  distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef _SMART_CARD_READER_IMPL_H_
+#define _SMART_CARD_READER_IMPL_H_
+
+#include <Protocol/SmartCardReader.h>
+
+EFI_STATUS
+EFIAPI
+SCardConnect (
+  IN     EFI_SMART_CARD_READER_PROTOCOL *This,
+  IN     UINT32                         AccessMode,
+  IN     UINT32                         CardAction,
+  IN     UINT32                         PreferredProtocols,
+     OUT UINT32                         *ActiveProtocol
+);
+
+EFI_STATUS
+EFIAPI
+SCardDisconnect (
+  IN EFI_SMART_CARD_READER_PROTOCOL *This,
+  IN UINT32                         CardAction
+);
+
+EFI_STATUS
+EFIAPI
+SCardStatus (
+  IN     EFI_SMART_CARD_READER_PROTOCOL *This,
+     OUT CHAR16                         *ReaderName,
+  IN OUT UINTN                          *ReaderNameLength,
+     OUT UINT32                         *State,
+     OUT UINT32                         *CardProtocol,
+     OUT UINT8                          *Atr,
+  IN OUT UINTN                          *AtrLength
+);
+
+EFI_STATUS
+EFIAPI
+SCardTransmit (
+  IN     EFI_SMART_CARD_READER_PROTOCOL *This,
+  IN     UINT8                          *CAPDU,
+  IN     UINTN                          CAPDULength,
+     OUT UINT8                          *RAPDU,
+  IN OUT UINTN                          *RAPDULength
+);
+
+EFI_STATUS
+EFIAPI
+SCardControl (
+  IN     EFI_SMART_CARD_READER_PROTOCOL *This,
+  IN     UINT32                         ControlCode,
+  IN     UINT8                          *InBuffer,
+  IN     UINTN                          InBufferLength,
+     OUT UINT8                          *OutBuffer,
+  IN OUT UINTN                          *OutBufferLength
+);
+
+EFI_STATUS
+EFIAPI
+SCardGetAttrib (
+  IN EFI_SMART_CARD_READER_PROTOCOL *This,
+  IN UINT32 Attrib,
+  OUT UINT8 *OutBuffer,
+  IN OUT UINTN *OutBufferLength
+);
+
+#endif
+
diff --git a/MdeModulePkg/Library/SmartCardReader/config.h 
b/MdeModulePkg/Library/SmartCardReader/config.h
new file mode 100644
index 0000000..b02352e
--- /dev/null
+++ b/MdeModulePkg/Library/SmartCardReader/config.h
@@ -0,0 +1,64 @@
+/*
+Copyright (c) 2014, Gemalto. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in
+  the documentation and/or other materials provided with the
+  distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/* we build for the UEFI driver */
+#define UEFI_DRIVER
+
+/* no log or debug messages */
+#define NO_LOG
+
+/* Adapt types used in libccid/ to UEFI types */
+#define size_t long
+#ifndef uint8_t
+#define uint8_t unsigned char
+#endif
+#define uint32_t UINT32
+
+#define MAX_BUFFER_SIZE_EXTENDED    (4 + 3 + (1<<16) + 3 + 2)   /**< enhanced 
(64K + APDU + Lc + Le + SW) Tx/Rx Buffer */
+
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+
+/* Use UEFI functions instead of C/Unix ones */
+#define free(a) FreePool(a)
+#define getenv(a) NULL
+#define malloc(a) AllocateZeroPool(a)
+#define memcpy CopyMem
+#define memmove CopyMem
+#define memset(buffer, value, length) SetMem(buffer, length, value)
+#define sleep(a) a
+#define strncmp(s1, s2, n) -1
+#define strerror(a) ""
+#define memcmp CompareMem
+
+/* TODO */
+#define usleep(a) 1
+#define ENODEV -1
+#define errno -1
+#define htonl(a) (a)
+
diff --git a/MdeModulePkg/Library/SmartCardReader/debug.c 
b/MdeModulePkg/Library/SmartCardReader/debug.c
new file mode 100644
index 0000000..a45e545
--- /dev/null
+++ b/MdeModulePkg/Library/SmartCardReader/debug.c
@@ -0,0 +1,62 @@
+/*
+Copyright (c) 2014, Gemalto. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in
+  the documentation and/or other materials provided with the
+  distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "config.h"
+#include "debuglog.h"
+
+#include <Library/UefiLib.h>
+
+void
+log_xxd(
+  const int priority,
+  const char *msg,
+  const unsigned char *buffer,
+  const int len)
+{
+  UINTN i;
+
+  (void)priority;
+
+  switch(msg[0])
+  {
+    case '>':
+      Print(L"-> ");
+      break;
+    case '<':
+      Print(L"<- ");
+      break;
+  }
+
+  for (i = 0; i < len; ++i)
+  {
+    /* 2 hex characters, 1 space, 1 NUL : total 4 characters */
+    Print(L" %02X", buffer[i]);
+  }
+
+  Print(L"\n");
+} /* log_xxd */
diff --git a/MdeModulePkg/Library/SmartCardReader/debuglog.h 
b/MdeModulePkg/Library/SmartCardReader/debuglog.h
new file mode 100644
index 0000000..a0a2a70
--- /dev/null
+++ b/MdeModulePkg/Library/SmartCardReader/debuglog.h
@@ -0,0 +1,81 @@
+/*
+Copyright (c) 2014, Gemalto. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in
+  the documentation and/or other materials provided with the
+  distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/** @file
+  TODO: Brief Description of UEFI Driver SmartCardReader
+
+  TODO: Detailed Description of UEFI Driver SmartCardReader
+
+**/
+
+#ifndef __EFI_DEBUGLOG_H__
+#define __EFI_DEBUGLOG_H__
+
+#include "config.h"
+#include <Uefi.h>
+
+//
+// Libraries
+//
+#include <Library/DebugLib.h>
+
+
+
+/* Debug macros */
+#ifdef NO_LOG
+
+#define Log0(priority) do { } while(0)
+#define Log1(priority, fmt) do { } while(0)
+#define Log2(priority, fmt, data) do { } while(0)
+#define Log3(priority, fmt, data1, data2) do { } while(0)
+#define Log4(priority, fmt, data1, data2, data3) do { } while(0)
+#define Log5(priority, fmt, data1, data2, data3, data4) do { } while(0)
+#define Log9(priority, fmt, data1, data2, data3, data4, data5, data6, data7, 
data8) do { } while(0)
+#define LogXxd(priority, msg, buffer, size) do { } while(0)
+
+#else
+
+#define Log0(priority) DEBUG((priority, "%d:%a()\n", __LINE__, __FUNCTION__))
+#define Log1(priority, fmt) DEBUG((priority, "%d:%a() " fmt "\n", __LINE__, 
__FUNCTION__))
+#define Log2(priority, fmt, data) DEBUG((priority, "%d:%a() " fmt "\n", 
__LINE__, __FUNCTION__, data))
+#define Log3(priority, fmt, data1, data2) DEBUG((priority, "%d:%a() " fmt 
"\n", __LINE__, __FUNCTION__, data1, data2))
+#define Log4(priority, fmt, data1, data2, data3) DEBUG((priority, "%d:%a() " 
fmt "\n", __LINE__, __FUNCTION__, data1, data2, data3))
+#define Log5(priority, fmt, data1, data2, data3, data4) DEBUG((priority, 
"%d:%a() " fmt "\n", __LINE__, __FUNCTION__, data1, data2, data3, data4))
+#define Log9(priority, fmt, data1, data2, data3, data4, data5, data6, data7, 
data8) DEBUG((priority, "%d:%a() " fmt "\n", __LINE__, __FUNCTION__, data1, 
data2, data3, data4, data5, data6, data7, data8))
+#define LogXxd(priority, msg, buffer, size) log_xxd((priority, msg, buffer, 
size))
+#endif
+
+#define PCSC_LOG_DEBUG EFI_D_WARN
+#define PCSC_LOG_INFO EFI_D_INFO
+#define PCSC_LOG_ERROR EFI_D_ERROR
+#define PCSC_LOG_CRITICAL EFI_D_ERROR
+
+void log_xxd(const int priority, const char *msg,
+    const unsigned char *buffer, const int size);
+
+#endif
-- 
2.1.4


------------------------------------------------------------------------------
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/edk2-devel

Reply via email to