示例#1
0
文件: SdBlockIo.c 项目: MattDevo/edk2
/**
  Send command SET_RELATIVE_ADDRESS to the device to set the device address.

  @param[in]  Device            A pointer to the SD_DEVICE instance.
  @param[out] Rca               The relative device address to assign.

  @retval EFI_SUCCESS           The request is executed successfully.
  @retval EFI_OUT_OF_RESOURCES  The request could not be executed due to a lack of resources.
  @retval Others                The request could not be executed successfully.

**/
EFI_STATUS
SdSetRca (
  IN     SD_DEVICE              *Device,
     OUT UINT16                 *Rca
  )
{
  EFI_STATUS                           Status;
  EFI_SD_MMC_PASS_THRU_PROTOCOL        *PassThru;
  EFI_SD_MMC_COMMAND_BLOCK             SdMmcCmdBlk;
  EFI_SD_MMC_STATUS_BLOCK              SdMmcStatusBlk;
  EFI_SD_MMC_PASS_THRU_COMMAND_PACKET  Packet;

  PassThru = Device->Private->PassThru;

  ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
  ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
  ZeroMem (&Packet, sizeof (Packet));
  Packet.SdMmcCmdBlk    = &SdMmcCmdBlk;
  Packet.SdMmcStatusBlk = &SdMmcStatusBlk;
  Packet.Timeout        = SD_GENERIC_TIMEOUT;

  SdMmcCmdBlk.CommandIndex = SD_SET_RELATIVE_ADDR;
  SdMmcCmdBlk.CommandType  = SdMmcCommandTypeBcr;
  SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR6;

  Status = PassThru->PassThru (PassThru, Device->Slot, &Packet, NULL);
  if (!EFI_ERROR (Status)) {
    DEBUG ((EFI_D_INFO, "Set RCA succeeds with Resp0 = 0x%x\n", SdMmcStatusBlk.Resp0));
    *Rca = (UINT16)(SdMmcStatusBlk.Resp0 >> 16);
  }
示例#2
0
/**
  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
EmmcDxeDriverBindingStart (
  IN EFI_DRIVER_BINDING_PROTOCOL   *This,
  IN EFI_HANDLE                    Controller,
  IN EFI_DEVICE_PATH_PROTOCOL      *RemainingDevicePath
  )
{
  EFI_STATUS                       Status;
  EFI_SD_MMC_PASS_THRU_PROTOCOL    *PassThru;
  EFI_DEVICE_PATH_PROTOCOL         *ParentDevicePath;
  EMMC_DRIVER_PRIVATE_DATA         *Private;
  UINT8                            Slot;

  Private  = NULL;
  PassThru = NULL;
  Status = gBS->OpenProtocol (
                  Controller,
                  &gEfiSdMmcPassThruProtocolGuid,
                  (VOID **) &PassThru,
                  This->DriverBindingHandle,
                  Controller,
                  EFI_OPEN_PROTOCOL_BY_DRIVER
                  );
  if ((EFI_ERROR (Status)) && (Status != EFI_ALREADY_STARTED)) {
    return Status;
  }

  //
  // Check EFI_ALREADY_STARTED to reuse the original EMMC_DRIVER_PRIVATE_DATA.
  //
  if (Status != EFI_ALREADY_STARTED) {
    Private = AllocateZeroPool (sizeof (EMMC_DRIVER_PRIVATE_DATA));
    if (Private == NULL) {
      Status = EFI_OUT_OF_RESOURCES;
      goto Error;
    }

    Status = gBS->OpenProtocol (
                    Controller,
                    &gEfiDevicePathProtocolGuid,
                    (VOID **) &ParentDevicePath,
                    This->DriverBindingHandle,
                    Controller,
                    EFI_OPEN_PROTOCOL_GET_PROTOCOL
                    );
    ASSERT_EFI_ERROR (Status);
    Private->PassThru            = PassThru;
    Private->Controller          = Controller;
    Private->ParentDevicePath    = ParentDevicePath;
    Private->DriverBindingHandle = This->DriverBindingHandle;

    Status = gBS->InstallProtocolInterface (
                    &Controller,
                    &gEfiCallerIdGuid,
                    EFI_NATIVE_INTERFACE,
                    Private
                    );
    if (EFI_ERROR (Status)) {
      goto Error;
    }
  } else {
    Status = gBS->OpenProtocol (
                    Controller,
                    &gEfiCallerIdGuid,
                    (VOID **) &Private,
                    This->DriverBindingHandle,
                    Controller,
                    EFI_OPEN_PROTOCOL_GET_PROTOCOL
                    );
    if (EFI_ERROR (Status)) {
      goto Error;
    }
  }

  if (RemainingDevicePath == NULL) {
    Slot = 0xFF;
    while (TRUE) {
      Status = PassThru->GetNextSlot (PassThru, &Slot);
      if (EFI_ERROR (Status)) {
        //
        // Cannot find more legal slots.
        //
        Status = EFI_SUCCESS;
        break;
      }

      Status = DiscoverEmmcDevice (Private, Slot, NULL);
      if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {
        break;
      }
    }
  } else if (!IsDevicePathEnd (RemainingDevicePath)) {
    Status = PassThru->GetSlotNumber (PassThru, RemainingDevicePath, &Slot);
    if (!EFI_ERROR (Status)) {
      Status = DiscoverEmmcDevice (Private, Slot, NextDevicePathNode (RemainingDevicePath));
    }
  }

Error:
  if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {
    gBS->CloseProtocol (
           Controller,
           &gEfiSdMmcPassThruProtocolGuid,
           This->DriverBindingHandle,
           Controller
           );

    if (Private != NULL) {
      gBS->UninstallMultipleProtocolInterfaces (
             Controller,
             &gEfiCallerIdGuid,
             Private,
             NULL
             );
      FreePool (Private);
    }
  }
  return Status;
}
示例#3
0
/**
  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
EmmcDxeDriverBindingSupported (
  IN EFI_DRIVER_BINDING_PROTOCOL   *This,
  IN EFI_HANDLE                    Controller,
  IN EFI_DEVICE_PATH_PROTOCOL      *RemainingDevicePath
  )
{
  EFI_STATUS                       Status;
  EFI_DEVICE_PATH_PROTOCOL         *ParentDevicePath;
  EFI_SD_MMC_PASS_THRU_PROTOCOL    *PassThru;
  UINT8                            Slot;

  //
  // Test EFI_SD_MMC_PASS_THRU_PROTOCOL on the controller handle.
  //
  Status = gBS->OpenProtocol (
                  Controller,
                  &gEfiSdMmcPassThruProtocolGuid,
                  (VOID**) &PassThru,
                  This->DriverBindingHandle,
                  Controller,
                  EFI_OPEN_PROTOCOL_BY_DRIVER
                  );

  if (Status == EFI_ALREADY_STARTED) {
    return EFI_SUCCESS;
  }

  if (EFI_ERROR (Status)) {
    return Status;
  }

  //
  // Test RemainingDevicePath is valid or not.
  //
  if ((RemainingDevicePath != NULL) && !IsDevicePathEnd (RemainingDevicePath)) {
    Status = PassThru->GetSlotNumber (PassThru, RemainingDevicePath, &Slot);
    if (EFI_ERROR (Status)) {
      //
      // Close the I/O Abstraction(s) used to perform the supported test
      //
      gBS->CloseProtocol (
             Controller,
             &gEfiSdMmcPassThruProtocolGuid,
             This->DriverBindingHandle,
             Controller
             );
      return Status;
    }
  }

  //
  // Close the I/O Abstraction(s) used to perform the supported test
  //
  gBS->CloseProtocol (
         Controller,
         &gEfiSdMmcPassThruProtocolGuid,
         This->DriverBindingHandle,
         Controller
         );

  //
  // Open the EFI Device Path protocol needed to perform the supported test
  //
  Status = gBS->OpenProtocol (
                  Controller,
                  &gEfiDevicePathProtocolGuid,
                  (VOID **) &ParentDevicePath,
                  This->DriverBindingHandle,
                  Controller,
                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
                  );
  return Status;
}
示例#4
0
/**
  Scan EMMC Bus to discover the device.

  @param[in]  Private             The EMMC driver private data structure.
  @param[in]  Slot                The slot number to check device present.
  @param[in]  RemainingDevicePath The pointer to the remaining device path.

  @retval EFI_SUCCESS             Successfully to discover the device and attach
                                  SdMmcIoProtocol to it.
  @retval EFI_OUT_OF_RESOURCES    The request could not be completed due to a lack
                                  of resources.
  @retval EFI_ALREADY_STARTED     The device was discovered before.
  @retval Others                  Fail to discover the device.

**/
EFI_STATUS
EFIAPI
DiscoverEmmcDevice (
  IN  EMMC_DRIVER_PRIVATE_DATA    *Private,
  IN  UINT8                       Slot,
  IN  EFI_DEVICE_PATH_PROTOCOL    *RemainingDevicePath
  )
{
  EFI_STATUS                      Status;
  EMMC_DEVICE                     *Device;
  EFI_DEVICE_PATH_PROTOCOL        *DevicePath;
  EFI_DEVICE_PATH_PROTOCOL        *NewDevicePath;
  EFI_DEVICE_PATH_PROTOCOL        *RemainingEmmcDevPath;
  EFI_DEV_PATH                    *Node;
  EFI_HANDLE                      DeviceHandle;
  EFI_SD_MMC_PASS_THRU_PROTOCOL   *PassThru;
  UINT8                           Index;

  Device              = NULL;
  DevicePath          = NULL;
  NewDevicePath       = NULL;
  RemainingDevicePath = NULL;
  PassThru = Private->PassThru;
  Device   = &Private->Device[Slot];

  //
  // Build Device Path to check if the EMMC device present at the slot.
  //
  Status = PassThru->BuildDevicePath (
                       PassThru,
                       Slot,
                       &DevicePath
                       );
  if (EFI_ERROR(Status)) {
    return Status;
  }

  if (DevicePath->SubType != MSG_EMMC_DP) {
    Status = EFI_UNSUPPORTED;
    goto Error;
  }

  NewDevicePath = AppendDevicePathNode (
                    Private->ParentDevicePath,
                    DevicePath
                    );
  if (NewDevicePath == NULL) {
    Status = EFI_OUT_OF_RESOURCES;
    goto Error;
  }

  DeviceHandle         = NULL;
  RemainingEmmcDevPath = NewDevicePath;
  Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &RemainingEmmcDevPath, &DeviceHandle);
  //
  // The device path to the EMMC device doesn't exist. It means the corresponding device private data hasn't been initialized.
  //
  if (EFI_ERROR (Status) || (DeviceHandle == NULL) || !IsDevicePathEnd (RemainingEmmcDevPath)) {
    Device->DevicePath = NewDevicePath;
    Device->Slot       = Slot;
    Device->Private    = Private;
    //
    // Expose user area in the Sd memory card to upper layer.
    //
    Status = DiscoverAllPartitions (Device);
    if (EFI_ERROR(Status)) {
      FreePool (NewDevicePath);
      goto Error;
    }

    Status = gBS->InstallProtocolInterface (
                    &Device->Handle,
                    &gEfiDevicePathProtocolGuid,
                    EFI_NATIVE_INTERFACE,
                    Device->DevicePath
                    );
    if (EFI_ERROR(Status)) {
      FreePool (NewDevicePath);
      goto Error;
    }

    Device->ControllerNameTable = NULL;
    GetEmmcModelName (Device, &Device->Cid);
    AddUnicodeString2 (
      "eng",
      gEmmcDxeComponentName.SupportedLanguages,
      &Device->ControllerNameTable,
      Device->ModelName,
      TRUE
      );
    AddUnicodeString2 (
      "en",
      gEmmcDxeComponentName.SupportedLanguages,
      &Device->ControllerNameTable,
      Device->ModelName,
      FALSE
      );
  }

  if (RemainingDevicePath == NULL) {
    //
    // Expose all partitions in the Emmc device to upper layer.
    //
    for (Index = 0; Index < EMMC_MAX_PARTITIONS; Index++) {
      InstallProtocolOnPartition (Device, Index);
    }
  } else if (!IsDevicePathEnd (RemainingDevicePath)) {
    //
    // Enumerate the specified partition
    //
    Node = (EFI_DEV_PATH *) RemainingDevicePath;
    if ((DevicePathType (&Node->DevPath) != HARDWARE_DEVICE_PATH) ||
        (DevicePathSubType (&Node->DevPath) != HW_CONTROLLER_DP) ||
        (DevicePathNodeLength (&Node->DevPath) != sizeof (CONTROLLER_DEVICE_PATH))) {
      Status = EFI_INVALID_PARAMETER;
      goto Error;
    }

    Index = (UINT8)Node->Controller.ControllerNumber;
    if (Index >= EMMC_MAX_PARTITIONS) {
      Status = EFI_INVALID_PARAMETER;
      goto Error;
    }

    Status = InstallProtocolOnPartition (Device, Index);
  }

Error:
  FreePool (DevicePath);

  return Status;
}
示例#5
0
文件: SdDxe.c 项目: lersek/edk2
/**
  Scan SD Bus to discover the device.

  @param[in]  Private             The SD driver private data structure.
  @param[in]  Slot                The slot number to check device present.

  @retval EFI_SUCCESS             Successfully to discover the device and attach
                                  SdMmcIoProtocol to it.
  @retval EFI_OUT_OF_RESOURCES    The request could not be completed due to a lack
                                  of resources.
  @retval EFI_ALREADY_STARTED     The device was discovered before.
  @retval Others                  Fail to discover the device.

**/
EFI_STATUS
EFIAPI
DiscoverSdDevice (
  IN  SD_DRIVER_PRIVATE_DATA      *Private,
  IN  UINT8                       Slot
  )
{
  EFI_STATUS                      Status;
  SD_DEVICE                       *Device;
  EFI_DEVICE_PATH_PROTOCOL        *DevicePath;
  EFI_DEVICE_PATH_PROTOCOL        *NewDevicePath;
  EFI_DEVICE_PATH_PROTOCOL        *RemainingDevicePath;
  EFI_HANDLE                      DeviceHandle;
  EFI_SD_MMC_PASS_THRU_PROTOCOL   *PassThru;

  Device              = NULL;
  DevicePath          = NULL;
  NewDevicePath       = NULL;
  RemainingDevicePath = NULL;
  PassThru = Private->PassThru;

  //
  // Build Device Path
  //
  Status = PassThru->BuildDevicePath (
                       PassThru,
                       Slot,
                       &DevicePath
                       );
  if (EFI_ERROR(Status)) {
    return Status;
  }

  if (DevicePath->SubType != MSG_SD_DP) {
    Status = EFI_UNSUPPORTED;
    goto Error;
  }

  NewDevicePath = AppendDevicePathNode (
                    Private->ParentDevicePath,
                    DevicePath
                    );

  if (NewDevicePath == NULL) {
    Status = EFI_OUT_OF_RESOURCES;
    goto Error;
  }

  DeviceHandle = NULL;
  RemainingDevicePath = NewDevicePath;
  Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &RemainingDevicePath, &DeviceHandle);
  if (!EFI_ERROR (Status) && (DeviceHandle != NULL) && IsDevicePathEnd(RemainingDevicePath)) {
    //
    // The device has been started, directly return to fast boot.
    //
    Status = EFI_ALREADY_STARTED;
    goto Error;
  }

  //
  // Allocate buffer to store SD_DEVICE private data.
  //
  Device = AllocateCopyPool (sizeof (SD_DEVICE), &mSdDeviceTemplate);
  if (Device == NULL) {
    Status = EFI_OUT_OF_RESOURCES;
    goto Error;
  }

  Device->DevicePath = NewDevicePath;
  Device->Slot       = Slot;
  Device->Private    = Private;
  InitializeListHead (&Device->Queue);

  //
  // Expose user area in the Sd memory card to upper layer.
  //
  Status = DiscoverUserArea (Device);
  if (EFI_ERROR(Status)) {
    goto Error;
  }

  Device->ControllerNameTable = NULL;
  AddUnicodeString2 (
    "eng",
    gSdDxeComponentName.SupportedLanguages,
    &Device->ControllerNameTable,
    Device->ModelName,
    TRUE
    );
  AddUnicodeString2 (
    "en",
    gSdDxeComponentName2.SupportedLanguages,
    &Device->ControllerNameTable,
    Device->ModelName,
    FALSE
    );

  Status = gBS->InstallMultipleProtocolInterfaces (
                  &Device->Handle,
                  &gEfiDevicePathProtocolGuid,
                  Device->DevicePath,
                  &gEfiBlockIoProtocolGuid,
                  &Device->BlockIo,
                  &gEfiBlockIo2ProtocolGuid,
                  &Device->BlockIo2,
                  &gEfiEraseBlockProtocolGuid,
                  &Device->EraseBlock,
                  &gEfiDiskInfoProtocolGuid,
                  &Device->DiskInfo,
                  NULL
                  );

  if (!EFI_ERROR (Status)) {
    gBS->OpenProtocol (
           Private->Controller,
           &gEfiSdMmcPassThruProtocolGuid,
           (VOID **) &(Private->PassThru),
           Private->DriverBindingHandle,
           Device->Handle,
           EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
           );
  }

Error:
  FreePool (DevicePath);

  if (EFI_ERROR (Status) && (NewDevicePath != NULL)) {
    FreePool (NewDevicePath);
  }

  if (EFI_ERROR (Status) && (Device != NULL)) {
    FreePool (Device);
  }

  return Status;
}