aboutsummaryrefslogtreecommitdiffstats
path: root/roms/edk2/MdeModulePkg/Bus/Scsi/ScsiBusDxe
diff options
context:
space:
mode:
Diffstat (limited to 'roms/edk2/MdeModulePkg/Bus/Scsi/ScsiBusDxe')
-rw-r--r--roms/edk2/MdeModulePkg/Bus/Scsi/ScsiBusDxe/ComponentName.c171
-rw-r--r--roms/edk2/MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBus.c1520
-rw-r--r--roms/edk2/MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBus.h486
-rw-r--r--roms/edk2/MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBus.uni17
-rw-r--r--roms/edk2/MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBusDxe.inf64
-rw-r--r--roms/edk2/MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBusExtra.uni14
6 files changed, 2272 insertions, 0 deletions
diff --git a/roms/edk2/MdeModulePkg/Bus/Scsi/ScsiBusDxe/ComponentName.c b/roms/edk2/MdeModulePkg/Bus/Scsi/ScsiBusDxe/ComponentName.c
new file mode 100644
index 000000000..e56eefee3
--- /dev/null
+++ b/roms/edk2/MdeModulePkg/Bus/Scsi/ScsiBusDxe/ComponentName.c
@@ -0,0 +1,171 @@
+/** @file
+ UEFI Component Name(2) protocol implementation for SCSI bus driver.
+
+Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+
+#include "ScsiBus.h"
+
+//
+// EFI Component Name Protocol
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gScsiBusComponentName = {
+ ScsiBusComponentNameGetDriverName,
+ ScsiBusComponentNameGetControllerName,
+ "eng"
+};
+
+//
+// EFI Component Name 2 Protocol
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gScsiBusComponentName2 = {
+ (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) ScsiBusComponentNameGetDriverName,
+ (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) ScsiBusComponentNameGetControllerName,
+ "en"
+};
+
+
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mScsiBusDriverNameTable[] = {
+ { "eng;en", (CHAR16 *) L"SCSI Bus Driver" },
+ { NULL , NULL }
+};
+
+/**
+ Retrieves a Unicode string that is the user readable name of the driver.
+
+ This function retrieves the user readable name of a driver in the form of a
+ Unicode string. If the driver specified by This has a user readable name in
+ the language specified by Language, then a pointer to the driver name is
+ returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
+ by This does not support the language specified by Language,
+ then EFI_UNSUPPORTED is returned.
+
+ @param This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param Language A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified
+ in RFC 4646 or ISO 639-2 language code format.
+
+ @param DriverName 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
+ScsiBusComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ )
+{
+ return LookupUnicodeString2 (
+ Language,
+ This->SupportedLanguages,
+ mScsiBusDriverNameTable,
+ DriverName,
+ (BOOLEAN)(This == &gScsiBusComponentName)
+ );
+}
+
+/**
+ Retrieves a Unicode string that is the user readable name of the controller
+ that is being managed by a driver.
+
+ This function retrieves the user readable name of the controller specified by
+ ControllerHandle and ChildHandle in the form of a Unicode string. If the
+ driver specified by This has a user readable name in the language specified by
+ Language, then a pointer to the controller name is returned in ControllerName,
+ and EFI_SUCCESS is returned. If the driver specified by This is not currently
+ managing the controller specified by ControllerHandle and ChildHandle,
+ then EFI_UNSUPPORTED is returned. If the driver specified by This does not
+ support the language specified by Language, then EFI_UNSUPPORTED is returned.
+
+ @param This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ 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 Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified in
+ RFC 4646 or ISO 639-2 language code format.
+
+ @param ControllerName 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
+ScsiBusComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ )
+{
+ return EFI_UNSUPPORTED;
+}
diff --git a/roms/edk2/MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBus.c b/roms/edk2/MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBus.c
new file mode 100644
index 000000000..27b554ad3
--- /dev/null
+++ b/roms/edk2/MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBus.c
@@ -0,0 +1,1520 @@
+/** @file
+ SCSI Bus driver that layers on every SCSI Pass Thru and
+ Extended SCSI Pass Thru protocol in the system.
+
+Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+
+#include "ScsiBus.h"
+
+
+EFI_DRIVER_BINDING_PROTOCOL gSCSIBusDriverBinding = {
+ SCSIBusDriverBindingSupported,
+ SCSIBusDriverBindingStart,
+ SCSIBusDriverBindingStop,
+ 0xa,
+ NULL,
+ NULL
+};
+
+VOID *mWorkingBuffer;
+
+/**
+ Convert EFI_SCSI_IO_SCSI_REQUEST_PACKET packet to EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET packet.
+
+ @param Packet The pointer of EFI_SCSI_IO_SCSI_REQUEST_PACKET
+ @param CommandPacket The pointer of EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET
+
+**/
+EFI_STATUS
+EFIAPI
+ScsiioToPassThruPacket (
+ IN EFI_SCSI_IO_SCSI_REQUEST_PACKET *Packet,
+ OUT EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *CommandPacket
+ );
+
+/**
+ Convert EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET packet to EFI_SCSI_IO_SCSI_REQUEST_PACKET packet.
+
+ @param ScsiPacket The pointer of EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET
+ @param Packet The pointer of EFI_SCSI_IO_SCSI_REQUEST_PACKET
+
+**/
+EFI_STATUS
+EFIAPI
+PassThruToScsiioPacket (
+ IN EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *ScsiPacket,
+ OUT EFI_SCSI_IO_SCSI_REQUEST_PACKET *Packet
+ );
+
+/**
+ Notify Function in which convert EFI1.0 PassThru Packet back to UEF2.0
+ SCSI IO Packet.
+
+ @param Event The instance of EFI_EVENT.
+ @param Context The parameter passed in.
+
+**/
+VOID
+EFIAPI
+NotifyFunction (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+/**
+ Allocates an aligned buffer for SCSI device.
+
+ This function allocates an aligned buffer for the SCSI device to perform
+ SCSI pass through operations. The alignment requirement is from SCSI pass
+ through interface.
+
+ @param ScsiIoDevice The SCSI child device involved for the operation.
+ @param BufferSize The request buffer size.
+
+ @return A pointer to the aligned buffer or NULL if the allocation fails.
+
+**/
+VOID *
+AllocateAlignedBuffer (
+ IN SCSI_IO_DEV *ScsiIoDevice,
+ IN UINTN BufferSize
+ )
+{
+ return AllocateAlignedPages (EFI_SIZE_TO_PAGES (BufferSize), ScsiIoDevice->ScsiIo.IoAlign);
+}
+
+/**
+ Frees an aligned buffer for SCSI device.
+
+ This function frees an aligned buffer for the SCSI device to perform
+ SCSI pass through operations.
+
+ @param Buffer The aligned buffer to be freed.
+ @param BufferSize The request buffer size.
+
+**/
+VOID
+FreeAlignedBuffer (
+ IN VOID *Buffer,
+ IN UINTN BufferSize
+ )
+{
+ if (Buffer != NULL) {
+ FreeAlignedPages (Buffer, EFI_SIZE_TO_PAGES (BufferSize));
+ }
+}
+
+/**
+ The user Entry Point for module ScsiBus. The user code starts with this function.
+
+ @param ImageHandle The firmware allocated handle for the EFI image.
+ @param SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The entry point is executed successfully.
+ @retval other Some error occurs when executing this entry point.
+
+**/
+EFI_STATUS
+EFIAPI
+InitializeScsiBus(
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Install driver model protocol(s).
+ //
+ Status = EfiLibInstallDriverBindingComponentName2 (
+ ImageHandle,
+ SystemTable,
+ &gSCSIBusDriverBinding,
+ ImageHandle,
+ &gScsiBusComponentName,
+ &gScsiBusComponentName2
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
+
+
+/**
+ Test to see if this driver supports ControllerHandle.
+
+ This service is called by the EFI boot service ConnectController(). In order
+ to make drivers as small as possible, there are a few calling restrictions for
+ this service. ConnectController() must follow these calling restrictions. If
+ any other agent wishes to call Supported() it must also follow these calling
+ restrictions.
+
+ @param This Protocol instance pointer.
+ @param ControllerHandle Handle of device to test
+ @param RemainingDevicePath Optional parameter use to pick a specific child
+ device to start.
+
+ @retval EFI_SUCCESS This driver supports this device
+ @retval EFI_ALREADY_STARTED This driver is already running on this device
+ @retval other This driver does not support this device
+
+**/
+EFI_STATUS
+EFIAPI
+SCSIBusDriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+{
+ EFI_STATUS Status;
+ EFI_SCSI_PASS_THRU_PROTOCOL *PassThru;
+ EFI_EXT_SCSI_PASS_THRU_PROTOCOL *ExtPassThru;
+ UINT64 Lun;
+ UINT8 *TargetId;
+ SCSI_TARGET_ID ScsiTargetId;
+
+ TargetId = &ScsiTargetId.ScsiId.ExtScsi[0];
+ SetMem (TargetId, TARGET_MAX_BYTES, 0xFF);
+
+ //
+ // To keep backward compatibility, UEFI ExtPassThru Protocol is supported as well as
+ // EFI PassThru Protocol. From priority perspective, ExtPassThru Protocol is firstly
+ // tried to open on host controller handle. If fails, then PassThru Protocol is tried instead.
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiExtScsiPassThruProtocolGuid,
+ (VOID **)&ExtPassThru,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+
+ if (Status == EFI_ALREADY_STARTED) {
+ return EFI_SUCCESS;
+ } else if (!EFI_ERROR(Status)) {
+ //
+ // Check if RemainingDevicePath is NULL or the End of Device Path Node,
+ // if yes, return EFI_SUCCESS.
+ //
+ if ((RemainingDevicePath == NULL) || IsDevicePathEnd (RemainingDevicePath)) {
+ //
+ // Close protocol regardless of RemainingDevicePath validation
+ //
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiExtScsiPassThruProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ return EFI_SUCCESS;
+ } else {
+ //
+ // If RemainingDevicePath isn't the End of Device Path Node, check its validation
+ //
+ Status = ExtPassThru->GetTargetLun (ExtPassThru, RemainingDevicePath, &TargetId, &Lun);
+ //
+ // Close protocol regardless of RemainingDevicePath validation
+ //
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiExtScsiPassThruProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ if (!EFI_ERROR(Status)) {
+ return EFI_SUCCESS;
+ }
+ }
+ }
+
+ //
+ // Come here in 2 condition:
+ // 1. ExtPassThru doesn't exist.
+ // 2. ExtPassThru exists but RemainingDevicePath is invalid.
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiScsiPassThruProtocolGuid,
+ (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->GetTargetLun (PassThru, RemainingDevicePath, &ScsiTargetId.ScsiId.Scsi, &Lun);
+ }
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiScsiPassThruProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ return Status;
+}
+
+
+/**
+ Start this driver on ControllerHandle.
+
+ This service is called by the EFI boot service ConnectController(). In order
+ to make drivers as small as possible, there are a few calling restrictions for
+ this service. ConnectController() must follow these calling restrictions. If
+ any other agent wishes to call Start() it must also follow these calling
+ restrictions.
+
+ @param This Protocol instance pointer.
+ @param ControllerHandle Handle of device to bind driver to
+ @param RemainingDevicePath Optional parameter use to pick a specific child
+ device to start.
+
+ @retval EFI_SUCCESS This driver is added to ControllerHandle
+ @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle
+ @retval other This driver does not support this device
+
+**/
+EFI_STATUS
+EFIAPI
+SCSIBusDriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+{
+ UINT64 Lun;
+ UINT8 *TargetId;
+ BOOLEAN ScanOtherPuns;
+ BOOLEAN FromFirstTarget;
+ BOOLEAN ExtScsiSupport;
+ EFI_STATUS Status;
+ EFI_STATUS DevicePathStatus;
+ EFI_STATUS PassThruStatus;
+ SCSI_BUS_DEVICE *ScsiBusDev;
+ SCSI_TARGET_ID ScsiTargetId;
+ EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
+ EFI_SCSI_PASS_THRU_PROTOCOL *ScsiInterface;
+ EFI_EXT_SCSI_PASS_THRU_PROTOCOL *ExtScsiInterface;
+ EFI_SCSI_BUS_PROTOCOL *BusIdentify;
+
+ TargetId = NULL;
+ ScanOtherPuns = TRUE;
+ FromFirstTarget = FALSE;
+ ExtScsiSupport = FALSE;
+ PassThruStatus = EFI_SUCCESS;
+
+ TargetId = &ScsiTargetId.ScsiId.ExtScsi[0];
+ SetMem (TargetId, TARGET_MAX_BYTES, 0xFF);
+
+ DevicePathStatus = gBS->OpenProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ (VOID **) &ParentDevicePath,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (DevicePathStatus) && (DevicePathStatus != EFI_ALREADY_STARTED)) {
+ return DevicePathStatus;
+ }
+
+ //
+ // Report Status Code to indicate SCSI bus starts
+ //
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+ EFI_PROGRESS_CODE,
+ (EFI_IO_BUS_SCSI | EFI_IOB_PC_INIT),
+ ParentDevicePath
+ );
+
+ //
+ // To keep backward compatibility, UEFI ExtPassThru Protocol is supported as well as
+ // EFI PassThru Protocol. From priority perspective, ExtPassThru Protocol is firstly
+ // tried to open on host controller handle. If fails, then PassThru Protocol is tried instead.
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiExtScsiPassThruProtocolGuid,
+ (VOID **) &ExtScsiInterface,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ //
+ // Fail to open UEFI ExtendPassThru Protocol, then try to open EFI PassThru Protocol instead.
+ //
+ if (EFI_ERROR(Status) && (Status != EFI_ALREADY_STARTED)) {
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiScsiPassThruProtocolGuid,
+ (VOID **) &ScsiInterface,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ //
+ // Fail to open EFI PassThru Protocol, Close the DevicePathProtocol if it is opened by this time.
+ //
+ if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {
+ if (!EFI_ERROR(DevicePathStatus)) {
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ }
+ return Status;
+ }
+ } else {
+ //
+ // Succeed to open ExtPassThru Protocol, and meanwhile open PassThru Protocol
+ // with BY_DRIVER if it is also present on the handle. The intent is to prevent
+ // another SCSI Bus Driver to work on the same host handle.
+ //
+ ExtScsiSupport = TRUE;
+ PassThruStatus = gBS->OpenProtocol (
+ Controller,
+ &gEfiScsiPassThruProtocolGuid,
+ (VOID **) &ScsiInterface,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ }
+
+ if (Status != EFI_ALREADY_STARTED) {
+ //
+ // Go through here means either ExtPassThru or PassThru Protocol is successfully opened
+ // on this handle for this time. Then construct Host controller private data.
+ //
+ ScsiBusDev = NULL;
+ ScsiBusDev = AllocateZeroPool(sizeof(SCSI_BUS_DEVICE));
+ if (ScsiBusDev == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ErrorExit;
+ }
+ ScsiBusDev->Signature = SCSI_BUS_DEVICE_SIGNATURE;
+ ScsiBusDev->ExtScsiSupport = ExtScsiSupport;
+ ScsiBusDev->DevicePath = ParentDevicePath;
+ if (ScsiBusDev->ExtScsiSupport) {
+ ScsiBusDev->ExtScsiInterface = ExtScsiInterface;
+ } else {
+ ScsiBusDev->ScsiInterface = ScsiInterface;
+ }
+
+ //
+ // Install EFI_SCSI_BUS_PROTOCOL to the controller handle, So ScsiBusDev could be
+ // retrieved on this controller handle. With ScsiBusDev, we can know which PassThru
+ // Protocol is present on the handle, UEFI ExtPassThru Protocol or EFI PassThru Protocol.
+ //
+ Status = gBS->InstallProtocolInterface (
+ &Controller,
+ &gEfiCallerIdGuid,
+ EFI_NATIVE_INTERFACE,
+ &ScsiBusDev->BusIdentify
+ );
+ if (EFI_ERROR (Status)) {
+ goto ErrorExit;
+ }
+ } else {
+ //
+ // Go through here means Start() is re-invoked again, nothing special is required to do except
+ // picking up Host controller private information.
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiCallerIdGuid,
+ (VOID **) &BusIdentify,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ ScsiBusDev = SCSI_BUS_CONTROLLER_DEVICE_FROM_THIS (BusIdentify);
+ }
+
+ //
+ // Report Status Code to indicate detecting devices on bus
+ //
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+ EFI_PROGRESS_CODE,
+ (EFI_IO_BUS_SCSI | EFI_IOB_PC_DETECT),
+ ParentDevicePath
+ );
+
+ Lun = 0;
+ if (RemainingDevicePath == NULL) {
+ //
+ // If RemainingDevicePath is NULL,
+ // must enumerate all SCSI devices anyway
+ //
+ FromFirstTarget = TRUE;
+ } else if (!IsDevicePathEnd (RemainingDevicePath)) {
+ //
+ // If RemainingDevicePath isn't the End of Device Path Node,
+ // only scan the specified device by RemainingDevicePath
+ //
+ if (ScsiBusDev->ExtScsiSupport) {
+ Status = ScsiBusDev->ExtScsiInterface->GetTargetLun (ScsiBusDev->ExtScsiInterface, RemainingDevicePath, &TargetId, &Lun);
+ } else {
+ Status = ScsiBusDev->ScsiInterface->GetTargetLun (ScsiBusDev->ScsiInterface, RemainingDevicePath, &ScsiTargetId.ScsiId.Scsi, &Lun);
+ }
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ } else {
+ //
+ // If RemainingDevicePath is the End of Device Path Node,
+ // skip enumerate any device and return EFI_SUCCESS
+ //
+ ScanOtherPuns = FALSE;
+ }
+
+ while(ScanOtherPuns) {
+ if (FromFirstTarget) {
+ //
+ // Remaining Device Path is NULL, scan all the possible Puns in the
+ // SCSI Channel.
+ //
+ if (ScsiBusDev->ExtScsiSupport) {
+ Status = ScsiBusDev->ExtScsiInterface->GetNextTargetLun (ScsiBusDev->ExtScsiInterface, &TargetId, &Lun);
+ } else {
+ Status = ScsiBusDev->ScsiInterface->GetNextDevice (ScsiBusDev->ScsiInterface, &ScsiTargetId.ScsiId.Scsi, &Lun);
+ }
+ if (EFI_ERROR (Status)) {
+ //
+ // no legal Pun and Lun found any more
+ //
+ break;
+ }
+ } else {
+ ScanOtherPuns = FALSE;
+ }
+ //
+ // Avoid creating handle for the host adapter.
+ //
+ if (ScsiBusDev->ExtScsiSupport) {
+ if ((ScsiTargetId.ScsiId.Scsi) == ScsiBusDev->ExtScsiInterface->Mode->AdapterId) {
+ continue;
+ }
+ } else {
+ if ((ScsiTargetId.ScsiId.Scsi) == ScsiBusDev->ScsiInterface->Mode->AdapterId) {
+ continue;
+ }
+ }
+ //
+ // Scan for the scsi device, if it attaches to the scsi bus,
+ // then create handle and install scsi i/o protocol.
+ //
+ Status = ScsiScanCreateDevice (This, Controller, &ScsiTargetId, Lun, ScsiBusDev);
+ }
+ return EFI_SUCCESS;
+
+ErrorExit:
+
+ if (ScsiBusDev != NULL) {
+ FreePool (ScsiBusDev);
+ }
+
+ if (ExtScsiSupport) {
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiExtScsiPassThruProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ if (!EFI_ERROR (PassThruStatus)) {
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiScsiPassThruProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ }
+ } else {
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiScsiPassThruProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ }
+ return Status;
+}
+
+/**
+ Stop this driver on ControllerHandle.
+
+ This service is called by the EFI boot service DisconnectController().
+ In order to make drivers as small as possible, there are a few calling
+ restrictions for this service. DisconnectController() must follow these
+ calling restrictions. If any other agent wishes to call Stop() it must also
+ follow these calling restrictions.
+
+ @param This Protocol instance pointer.
+ @param ControllerHandle Handle of device to stop driver on
+ @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
+ children is zero stop the entire bus driver.
+ @param ChildHandleBuffer List of Child Handles to Stop.
+
+ @retval EFI_SUCCESS This driver is removed ControllerHandle
+ @retval other This driver was not removed from this device
+
+**/
+EFI_STATUS
+EFIAPI
+SCSIBusDriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ )
+{
+ EFI_STATUS Status;
+ BOOLEAN AllChildrenStopped;
+ UINTN Index;
+ EFI_SCSI_IO_PROTOCOL *ScsiIo;
+ SCSI_IO_DEV *ScsiIoDevice;
+ VOID *ScsiPassThru;
+ EFI_SCSI_BUS_PROTOCOL *Scsidentifier;
+ SCSI_BUS_DEVICE *ScsiBusDev;
+
+ if (NumberOfChildren == 0) {
+ //
+ // Get the SCSI_BUS_DEVICE
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiCallerIdGuid,
+ (VOID **) &Scsidentifier,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ ScsiBusDev = SCSI_BUS_CONTROLLER_DEVICE_FROM_THIS (Scsidentifier);
+
+ //
+ // Uninstall SCSI Bus Protocol
+ //
+ gBS->UninstallProtocolInterface (
+ Controller,
+ &gEfiCallerIdGuid,
+ &ScsiBusDev->BusIdentify
+ );
+
+ //
+ // Close the bus driver
+ //
+ if (ScsiBusDev->ExtScsiSupport) {
+ //
+ // Close ExtPassThru Protocol from this controller handle
+ //
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiExtScsiPassThruProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ //
+ // When Start() succeeds to open ExtPassThru, it always tries to open PassThru BY_DRIVER.
+ // Its intent is to prevent another SCSI Bus Driver from working on the same host handle.
+ // So Stop() needs to try to close PassThru if present here.
+ //
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiScsiPassThruProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ } else {
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiScsiPassThruProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ }
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ FreePool (ScsiBusDev);
+ return EFI_SUCCESS;
+ }
+
+ AllChildrenStopped = TRUE;
+
+ for (Index = 0; Index < NumberOfChildren; Index++) {
+
+ Status = gBS->OpenProtocol (
+ ChildHandleBuffer[Index],
+ &gEfiScsiIoProtocolGuid,
+ (VOID **) &ScsiIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ AllChildrenStopped = FALSE;
+ continue;
+ }
+
+ ScsiIoDevice = SCSI_IO_DEV_FROM_THIS (ScsiIo);
+ //
+ // Close the child handle
+ //
+ if (ScsiIoDevice->ExtScsiSupport) {
+ Status = gBS->CloseProtocol (
+ Controller,
+ &gEfiExtScsiPassThruProtocolGuid,
+ This->DriverBindingHandle,
+ ChildHandleBuffer[Index]
+ );
+
+ } else {
+ Status = gBS->CloseProtocol (
+ Controller,
+ &gEfiScsiPassThruProtocolGuid,
+ This->DriverBindingHandle,
+ ChildHandleBuffer[Index]
+ );
+ }
+
+ Status = gBS->UninstallMultipleProtocolInterfaces (
+ ChildHandleBuffer[Index],
+ &gEfiDevicePathProtocolGuid,
+ ScsiIoDevice->DevicePath,
+ &gEfiScsiIoProtocolGuid,
+ &ScsiIoDevice->ScsiIo,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ AllChildrenStopped = FALSE;
+ if (ScsiIoDevice->ExtScsiSupport) {
+ gBS->OpenProtocol (
+ Controller,
+ &gEfiExtScsiPassThruProtocolGuid,
+ &ScsiPassThru,
+ This->DriverBindingHandle,
+ ChildHandleBuffer[Index],
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
+ );
+ } else {
+ gBS->OpenProtocol (
+ Controller,
+ &gEfiScsiPassThruProtocolGuid,
+ &ScsiPassThru,
+ This->DriverBindingHandle,
+ ChildHandleBuffer[Index],
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
+ );
+ }
+ } else {
+ FreePool (ScsiIoDevice);
+ }
+ }
+
+ if (!AllChildrenStopped) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Retrieves the device type information of the SCSI Controller.
+
+ @param This Protocol instance pointer.
+ @param DeviceType A pointer to the device type information retrieved from
+ the SCSI Controller.
+
+ @retval EFI_SUCCESS Retrieves the device type information successfully.
+ @retval EFI_INVALID_PARAMETER The DeviceType is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+ScsiGetDeviceType (
+ IN EFI_SCSI_IO_PROTOCOL *This,
+ OUT UINT8 *DeviceType
+ )
+{
+ SCSI_IO_DEV *ScsiIoDevice;
+
+ if (DeviceType == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ScsiIoDevice = SCSI_IO_DEV_FROM_THIS (This);
+ *DeviceType = ScsiIoDevice->ScsiDeviceType;
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Retrieves the device location in the SCSI channel.
+
+ @param This Protocol instance pointer.
+ @param Target A pointer to the Target ID of a SCSI device
+ on the SCSI channel.
+ @param Lun A pointer to the LUN of the SCSI device on
+ the SCSI channel.
+
+ @retval EFI_SUCCESS Retrieves the device location successfully.
+ @retval EFI_INVALID_PARAMETER The Target or Lun is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+ScsiGetDeviceLocation (
+ IN EFI_SCSI_IO_PROTOCOL *This,
+ IN OUT UINT8 **Target,
+ OUT UINT64 *Lun
+ )
+{
+ SCSI_IO_DEV *ScsiIoDevice;
+
+ if (Target == NULL || Lun == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ScsiIoDevice = SCSI_IO_DEV_FROM_THIS (This);
+
+ CopyMem (*Target,&ScsiIoDevice->Pun, TARGET_MAX_BYTES);
+
+ *Lun = ScsiIoDevice->Lun;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Resets the SCSI Bus that the SCSI Controller is attached to.
+
+ @param This Protocol instance pointer.
+
+ @retval EFI_SUCCESS The SCSI bus is reset successfully.
+ @retval EFI_DEVICE_ERROR Errors encountered when resetting the SCSI bus.
+ @retval EFI_UNSUPPORTED The bus reset operation is not supported by the
+ SCSI Host Controller.
+ @retval EFI_TIMEOUT A timeout occurred while attempting to reset
+ the SCSI bus.
+**/
+EFI_STATUS
+EFIAPI
+ScsiResetBus (
+ IN EFI_SCSI_IO_PROTOCOL *This
+ )
+{
+ SCSI_IO_DEV *ScsiIoDevice;
+
+ ScsiIoDevice = SCSI_IO_DEV_FROM_THIS (This);
+
+ //
+ // Report Status Code to indicate reset happens
+ //
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+ EFI_PROGRESS_CODE,
+ (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_PC_RESET),
+ ScsiIoDevice->ScsiBusDeviceData->DevicePath
+ );
+
+ if (ScsiIoDevice->ExtScsiSupport){
+ return ScsiIoDevice->ExtScsiPassThru->ResetChannel (ScsiIoDevice->ExtScsiPassThru);
+ } else {
+ return ScsiIoDevice->ScsiPassThru->ResetChannel (ScsiIoDevice->ScsiPassThru);
+ }
+}
+
+
+/**
+ Resets the SCSI Controller that the device handle specifies.
+
+ @param This Protocol instance pointer.
+
+ @retval EFI_SUCCESS Reset the SCSI controller successfully.
+ @retval EFI_DEVICE_ERROR Errors are encountered when resetting the SCSI Controller.
+ @retval EFI_UNSUPPORTED The SCSI bus does not support a device reset operation.
+ @retval EFI_TIMEOUT A timeout occurred while attempting to reset the
+ SCSI Controller.
+**/
+EFI_STATUS
+EFIAPI
+ScsiResetDevice (
+ IN EFI_SCSI_IO_PROTOCOL *This
+ )
+{
+ SCSI_IO_DEV *ScsiIoDevice;
+ UINT8 Target[TARGET_MAX_BYTES];
+
+ ScsiIoDevice = SCSI_IO_DEV_FROM_THIS (This);
+
+ //
+ // Report Status Code to indicate reset happens
+ //
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+ EFI_PROGRESS_CODE,
+ (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_PC_RESET),
+ ScsiIoDevice->ScsiBusDeviceData->DevicePath
+ );
+
+ CopyMem (Target,&ScsiIoDevice->Pun, TARGET_MAX_BYTES);
+
+
+ if (ScsiIoDevice->ExtScsiSupport) {
+ return ScsiIoDevice->ExtScsiPassThru->ResetTargetLun (
+ ScsiIoDevice->ExtScsiPassThru,
+ Target,
+ ScsiIoDevice->Lun
+ );
+ } else {
+ return ScsiIoDevice->ScsiPassThru->ResetTarget (
+ ScsiIoDevice->ScsiPassThru,
+ ScsiIoDevice->Pun.ScsiId.Scsi,
+ ScsiIoDevice->Lun
+ );
+ }
+}
+
+
+/**
+ Sends a SCSI Request Packet to the SCSI Controller for execution.
+
+ @param This Protocol instance pointer.
+ @param CommandPacket The SCSI request packet to send to the SCSI
+ Controller specified by the device handle.
+ @param Event If the SCSI bus where the SCSI device is attached
+ does not support non-blocking I/O, then Event is
+ ignored, and blocking I/O is performed.
+ If Event is NULL, then blocking I/O is performed.
+ If Event is not NULL and non-blocking I/O is
+ supported, then non-blocking I/O is performed,
+ and Event will be signaled when the SCSI Request
+ Packet completes.
+
+ @retval EFI_SUCCESS The SCSI Request Packet was sent by the host
+ successfully, and TransferLength bytes were
+ transferred to/from DataBuffer.See
+ HostAdapterStatus, TargetStatus,
+ SenseDataLength, and SenseData in that order
+ for additional status information.
+ @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed,
+ but the entire DataBuffer could not be transferred.
+ The actual number of bytes transferred is returned
+ in TransferLength. See HostAdapterStatus,
+ TargetStatus, SenseDataLength, and SenseData in
+ that order for additional status information.
+ @retval EFI_NOT_READY The SCSI Request Packet could not be sent because
+ there are too many SCSI Command Packets already
+ queued.The caller may retry again later.
+ @retval EFI_DEVICE_ERROR A device error occurred while attempting to send
+ the SCSI Request Packet. See HostAdapterStatus,
+ TargetStatus, SenseDataLength, and SenseData in
+ that order for additional status information.
+ @retval EFI_INVALID_PARAMETER The contents of CommandPacket are invalid.
+ The SCSI Request Packet was not sent, so no
+ additional status information is available.
+ @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet
+ is not supported by the SCSI initiator(i.e., SCSI
+ Host Controller). The SCSI Request Packet was not
+ sent, so no additional status information is
+ available.
+ @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI
+ Request Packet to execute. See HostAdapterStatus,
+ TargetStatus, SenseDataLength, and SenseData in
+ that order for additional status information.
+**/
+EFI_STATUS
+EFIAPI
+ScsiExecuteSCSICommand (
+ IN EFI_SCSI_IO_PROTOCOL *This,
+ IN OUT EFI_SCSI_IO_SCSI_REQUEST_PACKET *Packet,
+ IN EFI_EVENT Event OPTIONAL
+ )
+{
+ SCSI_IO_DEV *ScsiIoDevice;
+ EFI_STATUS Status;
+ UINT8 Target[TARGET_MAX_BYTES];
+ EFI_EVENT PacketEvent;
+ EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *ExtRequestPacket;
+ SCSI_EVENT_DATA EventData;
+
+ PacketEvent = NULL;
+
+ if (Packet == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ScsiIoDevice = SCSI_IO_DEV_FROM_THIS (This);
+ CopyMem (Target,&ScsiIoDevice->Pun, TARGET_MAX_BYTES);
+
+ if (ScsiIoDevice->ExtScsiSupport) {
+ ExtRequestPacket = (EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *) Packet;
+
+ if (((ScsiIoDevice->ExtScsiPassThru->Mode->Attributes & EFI_SCSI_PASS_THRU_ATTRIBUTES_NONBLOCKIO) != 0) && (Event != NULL)) {
+ Status = ScsiIoDevice->ExtScsiPassThru->PassThru (
+ ScsiIoDevice->ExtScsiPassThru,
+ Target,
+ ScsiIoDevice->Lun,
+ ExtRequestPacket,
+ Event
+ );
+ } else {
+ //
+ // If there's no event or the SCSI Device doesn't support NON-BLOCKING,
+ // let the 'Event' parameter for PassThru() be NULL.
+ //
+ Status = ScsiIoDevice->ExtScsiPassThru->PassThru (
+ ScsiIoDevice->ExtScsiPassThru,
+ Target,
+ ScsiIoDevice->Lun,
+ ExtRequestPacket,
+ NULL
+ );
+ if ((!EFI_ERROR(Status)) && (Event != NULL)) {
+ //
+ // Signal Event to tell caller to pick up the SCSI IO packet if the
+ // PassThru() succeeds.
+ //
+ gBS->SignalEvent (Event);
+ }
+ }
+ } else {
+
+ mWorkingBuffer = AllocatePool (sizeof(EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET));
+
+ if (mWorkingBuffer == NULL) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Convert package into EFI1.0, EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET.
+ //
+ Status = ScsiioToPassThruPacket(Packet, (EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET*)mWorkingBuffer);
+ if (EFI_ERROR(Status)) {
+ FreePool(mWorkingBuffer);
+ return Status;
+ }
+
+ if (((ScsiIoDevice->ScsiPassThru->Mode->Attributes & EFI_SCSI_PASS_THRU_ATTRIBUTES_NONBLOCKIO) != 0) && (Event != NULL)) {
+ EventData.Data1 = (VOID*)Packet;
+ EventData.Data2 = Event;
+ //
+ // Create Event
+ //
+ Status = gBS->CreateEvent (
+ EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ NotifyFunction,
+ &EventData,
+ &PacketEvent
+ );
+ if (EFI_ERROR(Status)) {
+ FreePool(mWorkingBuffer);
+ return Status;
+ }
+
+ Status = ScsiIoDevice->ScsiPassThru->PassThru (
+ ScsiIoDevice->ScsiPassThru,
+ ScsiIoDevice->Pun.ScsiId.Scsi,
+ ScsiIoDevice->Lun,
+ mWorkingBuffer,
+ PacketEvent
+ );
+
+ if (EFI_ERROR(Status)) {
+ FreePool(mWorkingBuffer);
+ gBS->CloseEvent(PacketEvent);
+ return Status;
+ }
+
+ } else {
+ //
+ // If there's no event or SCSI Device doesn't support NON-BLOCKING, just convert
+ // EFI1.0 PassThru packet back to UEFI2.0 SCSI IO Packet.
+ //
+ Status = ScsiIoDevice->ScsiPassThru->PassThru (
+ ScsiIoDevice->ScsiPassThru,
+ ScsiIoDevice->Pun.ScsiId.Scsi,
+ ScsiIoDevice->Lun,
+ mWorkingBuffer,
+ NULL
+ );
+ if (EFI_ERROR(Status)) {
+ FreePool(mWorkingBuffer);
+ return Status;
+ }
+
+ PassThruToScsiioPacket((EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET*)mWorkingBuffer,Packet);
+ //
+ // After converting EFI1.0 PassThru Packet back to UEFI2.0 SCSI IO Packet,
+ // free mWorkingBuffer.
+ //
+ FreePool(mWorkingBuffer);
+
+ //
+ // Signal Event to tell caller to pick up the SCSI IO Packet.
+ //
+ if (Event != NULL) {
+ gBS->SignalEvent (Event);
+ }
+ }
+ }
+ return Status;
+}
+
+
+/**
+ Scan SCSI Bus to discover the device, and attach ScsiIoProtocol to it.
+
+ @param This Protocol instance pointer
+ @param Controller Controller handle
+ @param TargetId Target to be scanned
+ @param Lun The Lun of the SCSI device on the SCSI channel.
+ @param ScsiBusDev The pointer of SCSI_BUS_DEVICE
+
+ @retval EFI_SUCCESS Successfully to discover the device and attach
+ ScsiIoProtocol to it.
+ @retval EFI_OUT_OF_RESOURCES Fail to discover the device.
+
+**/
+EFI_STATUS
+EFIAPI
+ScsiScanCreateDevice (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN SCSI_TARGET_ID *TargetId,
+ IN UINT64 Lun,
+ IN OUT SCSI_BUS_DEVICE *ScsiBusDev
+ )
+{
+ EFI_STATUS Status;
+ SCSI_IO_DEV *ScsiIoDevice;
+ EFI_DEVICE_PATH_PROTOCOL *ScsiDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath;
+ EFI_HANDLE DeviceHandle;
+
+ DevicePath = NULL;
+ RemainingDevicePath = NULL;
+ ScsiDevicePath = NULL;
+ ScsiIoDevice = NULL;
+
+ //
+ // Build Device Path
+ //
+ if (ScsiBusDev->ExtScsiSupport){
+ Status = ScsiBusDev->ExtScsiInterface->BuildDevicePath (
+ ScsiBusDev->ExtScsiInterface,
+ &TargetId->ScsiId.ExtScsi[0],
+ Lun,
+ &ScsiDevicePath
+ );
+ } else {
+ Status = ScsiBusDev->ScsiInterface->BuildDevicePath (
+ ScsiBusDev->ScsiInterface,
+ TargetId->ScsiId.Scsi,
+ Lun,
+ &ScsiDevicePath
+ );
+ }
+
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ DevicePath = AppendDevicePathNode (
+ ScsiBusDev->DevicePath,
+ ScsiDevicePath
+ );
+
+ if (DevicePath == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ErrorExit;
+ }
+
+ DeviceHandle = NULL;
+ RemainingDevicePath = DevicePath;
+ 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 ErrorExit;
+ }
+
+ ScsiIoDevice = AllocateZeroPool (sizeof (SCSI_IO_DEV));
+ if (ScsiIoDevice == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ErrorExit;
+ }
+
+ ScsiIoDevice->Signature = SCSI_IO_DEV_SIGNATURE;
+ ScsiIoDevice->ScsiBusDeviceData = ScsiBusDev;
+ CopyMem(&ScsiIoDevice->Pun, TargetId, TARGET_MAX_BYTES);
+ ScsiIoDevice->Lun = Lun;
+
+ if (ScsiBusDev->ExtScsiSupport) {
+ ScsiIoDevice->ExtScsiPassThru = ScsiBusDev->ExtScsiInterface;
+ ScsiIoDevice->ExtScsiSupport = TRUE;
+ ScsiIoDevice->ScsiIo.IoAlign = ScsiIoDevice->ExtScsiPassThru->Mode->IoAlign;
+
+ } else {
+ ScsiIoDevice->ScsiPassThru = ScsiBusDev->ScsiInterface;
+ ScsiIoDevice->ExtScsiSupport = FALSE;
+ ScsiIoDevice->ScsiIo.IoAlign = ScsiIoDevice->ScsiPassThru->Mode->IoAlign;
+ }
+
+ ScsiIoDevice->ScsiIo.GetDeviceType = ScsiGetDeviceType;
+ ScsiIoDevice->ScsiIo.GetDeviceLocation = ScsiGetDeviceLocation;
+ ScsiIoDevice->ScsiIo.ResetBus = ScsiResetBus;
+ ScsiIoDevice->ScsiIo.ResetDevice = ScsiResetDevice;
+ ScsiIoDevice->ScsiIo.ExecuteScsiCommand = ScsiExecuteSCSICommand;
+
+ //
+ // Report Status Code here since the new SCSI device will be discovered
+ //
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+ EFI_PROGRESS_CODE,
+ (EFI_IO_BUS_SCSI | EFI_IOB_PC_ENABLE),
+ ScsiBusDev->DevicePath
+ );
+
+ if (!DiscoverScsiDevice (ScsiIoDevice)) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ErrorExit;
+ }
+
+ ScsiIoDevice->DevicePath = DevicePath;
+
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &ScsiIoDevice->Handle,
+ &gEfiDevicePathProtocolGuid,
+ ScsiIoDevice->DevicePath,
+ &gEfiScsiIoProtocolGuid,
+ &ScsiIoDevice->ScsiIo,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ goto ErrorExit;
+ } else {
+ if (ScsiBusDev->ExtScsiSupport) {
+ gBS->OpenProtocol (
+ Controller,
+ &gEfiExtScsiPassThruProtocolGuid,
+ (VOID **) &(ScsiBusDev->ExtScsiInterface),
+ This->DriverBindingHandle,
+ ScsiIoDevice->Handle,
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
+ );
+ } else {
+ gBS->OpenProtocol (
+ Controller,
+ &gEfiScsiPassThruProtocolGuid,
+ (VOID **) &(ScsiBusDev->ScsiInterface),
+ This->DriverBindingHandle,
+ ScsiIoDevice->Handle,
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
+ );
+ }
+ }
+ return EFI_SUCCESS;
+
+ErrorExit:
+
+ //
+ // The memory space for ScsiDevicePath is allocated in
+ // ScsiPassThru->BuildDevicePath() function; It is no longer used
+ // after AppendDevicePathNode,so free the memory it occupies.
+ //
+ FreePool (ScsiDevicePath);
+
+ if (DevicePath != NULL) {
+ FreePool (DevicePath);
+ }
+
+ if (ScsiIoDevice != NULL) {
+ FreePool (ScsiIoDevice);
+ }
+
+ return Status;
+}
+
+
+/**
+ Discovery SCSI Device
+
+ @param ScsiIoDevice The pointer of SCSI_IO_DEV
+
+ @retval TRUE Find SCSI Device and verify it.
+ @retval FALSE Unable to find SCSI Device.
+
+**/
+BOOLEAN
+DiscoverScsiDevice (
+ IN OUT SCSI_IO_DEV *ScsiIoDevice
+ )
+{
+ EFI_STATUS Status;
+ UINT32 InquiryDataLength;
+ UINT8 SenseDataLength;
+ UINT8 HostAdapterStatus;
+ UINT8 TargetStatus;
+ EFI_SCSI_INQUIRY_DATA *InquiryData;
+ EFI_SCSI_SENSE_DATA *SenseData;
+ UINT8 MaxRetry;
+ UINT8 Index;
+ BOOLEAN ScsiDeviceFound;
+
+ HostAdapterStatus = 0;
+ TargetStatus = 0;
+ SenseData = NULL;
+
+ InquiryData = AllocateAlignedBuffer (ScsiIoDevice, sizeof (EFI_SCSI_INQUIRY_DATA));
+ if (InquiryData == NULL) {
+ ScsiDeviceFound = FALSE;
+ goto Done;
+ }
+
+ SenseData = AllocateAlignedBuffer (
+ ScsiIoDevice,
+ sizeof (EFI_SCSI_SENSE_DATA)
+ );
+ if (SenseData == NULL) {
+ ScsiDeviceFound = FALSE;
+ goto Done;
+ }
+
+ //
+ // Using Inquiry command to scan for the device
+ //
+ InquiryDataLength = sizeof (EFI_SCSI_INQUIRY_DATA);
+ SenseDataLength = sizeof (EFI_SCSI_SENSE_DATA);
+ ZeroMem (InquiryData, InquiryDataLength);
+ ZeroMem (SenseData, SenseDataLength);
+
+ MaxRetry = 2;
+ for (Index = 0; Index < MaxRetry; Index++) {
+ Status = ScsiInquiryCommand (
+ &ScsiIoDevice->ScsiIo,
+ SCSI_BUS_TIMEOUT,
+ SenseData,
+ &SenseDataLength,
+ &HostAdapterStatus,
+ &TargetStatus,
+ (VOID *) InquiryData,
+ &InquiryDataLength,
+ FALSE
+ );
+ if (!EFI_ERROR (Status)) {
+ if ((HostAdapterStatus == EFI_SCSI_IO_STATUS_HOST_ADAPTER_OK) &&
+ (TargetStatus == EFI_SCSI_IO_STATUS_TARGET_CHECK_CONDITION) &&
+ (SenseData->Error_Code == 0x70) &&
+ (SenseData->Sense_Key == EFI_SCSI_SK_ILLEGAL_REQUEST)) {
+ ScsiDeviceFound = FALSE;
+ goto Done;
+ }
+ break;
+ }
+ if ((Status == EFI_BAD_BUFFER_SIZE) ||
+ (Status == EFI_INVALID_PARAMETER) ||
+ (Status == EFI_UNSUPPORTED)) {
+ ScsiDeviceFound = FALSE;
+ goto Done;
+ }
+ }
+
+ if (Index == MaxRetry) {
+ ScsiDeviceFound = FALSE;
+ goto Done;
+ }
+
+ //
+ // Retrieved inquiry data successfully
+ //
+ if (InquiryData->Peripheral_Qualifier != 0) {
+ ScsiDeviceFound = FALSE;
+ goto Done;
+ }
+
+ if ((InquiryData->Peripheral_Type >= EFI_SCSI_TYPE_RESERVED_LOW) &&
+ (InquiryData->Peripheral_Type <= EFI_SCSI_TYPE_RESERVED_HIGH)) {
+ ScsiDeviceFound = FALSE;
+ goto Done;
+ }
+
+ //
+ // valid device type and peripheral qualifier combination.
+ //
+ ScsiIoDevice->ScsiDeviceType = InquiryData->Peripheral_Type;
+ ScsiIoDevice->RemovableDevice = InquiryData->Rmb;
+ if (InquiryData->Version == 0) {
+ ScsiIoDevice->ScsiVersion = 0;
+ } else {
+ //
+ // ANSI-approved version
+ //
+ ScsiIoDevice->ScsiVersion = (UINT8) (InquiryData->Version & 0x07);
+ }
+
+ ScsiDeviceFound = TRUE;
+
+Done:
+ FreeAlignedBuffer (SenseData, sizeof (EFI_SCSI_SENSE_DATA));
+ FreeAlignedBuffer (InquiryData, sizeof (EFI_SCSI_INQUIRY_DATA));
+
+ return ScsiDeviceFound;
+}
+
+
+/**
+ Convert EFI_SCSI_IO_SCSI_REQUEST_PACKET packet to EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET packet.
+
+ @param Packet The pointer of EFI_SCSI_IO_SCSI_REQUEST_PACKET
+ @param CommandPacket The pointer of EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET
+
+**/
+EFI_STATUS
+EFIAPI
+ScsiioToPassThruPacket (
+ IN EFI_SCSI_IO_SCSI_REQUEST_PACKET *Packet,
+ OUT EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *CommandPacket
+ )
+{
+ //
+ //EFI 1.10 doesn't support Bi-Direction Command.
+ //
+ if (Packet->DataDirection == EFI_SCSI_IO_DATA_DIRECTION_BIDIRECTIONAL) {
+ return EFI_UNSUPPORTED;
+ }
+
+ ZeroMem (CommandPacket, sizeof (EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET));
+
+ CommandPacket->Timeout = Packet->Timeout;
+ CommandPacket->Cdb = Packet->Cdb;
+ CommandPacket->CdbLength = Packet->CdbLength;
+ CommandPacket->DataDirection = Packet->DataDirection;
+ CommandPacket->HostAdapterStatus = Packet->HostAdapterStatus;
+ CommandPacket->TargetStatus = Packet->TargetStatus;
+ CommandPacket->SenseData = Packet->SenseData;
+ CommandPacket->SenseDataLength = Packet->SenseDataLength;
+
+ if (Packet->DataDirection == EFI_SCSI_IO_DATA_DIRECTION_READ) {
+ CommandPacket->DataBuffer = Packet->InDataBuffer;
+ CommandPacket->TransferLength = Packet->InTransferLength;
+ } else if (Packet->DataDirection == EFI_SCSI_IO_DATA_DIRECTION_WRITE) {
+ CommandPacket->DataBuffer = Packet->OutDataBuffer;
+ CommandPacket->TransferLength = Packet->OutTransferLength;
+ }
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Convert EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET packet to EFI_SCSI_IO_SCSI_REQUEST_PACKET packet.
+
+ @param ScsiPacket The pointer of EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET
+ @param Packet The pointer of EFI_SCSI_IO_SCSI_REQUEST_PACKET
+
+**/
+EFI_STATUS
+EFIAPI
+PassThruToScsiioPacket (
+ IN EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *ScsiPacket,
+ OUT EFI_SCSI_IO_SCSI_REQUEST_PACKET *Packet
+ )
+{
+ Packet->Timeout = ScsiPacket->Timeout;
+ Packet->Cdb = ScsiPacket->Cdb;
+ Packet->CdbLength = ScsiPacket->CdbLength;
+ Packet->DataDirection = ScsiPacket->DataDirection;
+ Packet->HostAdapterStatus = ScsiPacket->HostAdapterStatus;
+ Packet->TargetStatus = ScsiPacket->TargetStatus;
+ Packet->SenseData = ScsiPacket->SenseData;
+ Packet->SenseDataLength = ScsiPacket->SenseDataLength;
+
+ if (ScsiPacket->DataDirection == EFI_SCSI_IO_DATA_DIRECTION_READ) {
+ Packet->InDataBuffer = ScsiPacket->DataBuffer;
+ Packet->InTransferLength = ScsiPacket->TransferLength;
+ } else if (Packet->DataDirection == EFI_SCSI_IO_DATA_DIRECTION_WRITE) {
+ Packet->OutDataBuffer = ScsiPacket->DataBuffer;
+ Packet->OutTransferLength = ScsiPacket->TransferLength;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Notify Function in which convert EFI1.0 PassThru Packet back to UEF2.0
+ SCSI IO Packet.
+
+ @param Event The instance of EFI_EVENT.
+ @param Context The parameter passed in.
+
+**/
+VOID
+EFIAPI
+NotifyFunction (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_SCSI_IO_SCSI_REQUEST_PACKET *Packet;
+ EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *ScsiPacket;
+ EFI_EVENT CallerEvent;
+ SCSI_EVENT_DATA *PassData;
+
+ PassData = (SCSI_EVENT_DATA*)Context;
+ Packet = (EFI_SCSI_IO_SCSI_REQUEST_PACKET *)PassData->Data1;
+ ScsiPacket = (EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET*)mWorkingBuffer;
+
+ //
+ // Convert EFI1.0 PassThru packet to UEFI2.0 SCSI IO Packet.
+ //
+ PassThruToScsiioPacket(ScsiPacket, Packet);
+
+ //
+ // After converting EFI1.0 PassThru Packet back to UEFI2.0 SCSI IO Packet,
+ // free mWorkingBuffer.
+ //
+ gBS->FreePool(mWorkingBuffer);
+
+ //
+ // Signal Event to tell caller to pick up UEFI2.0 SCSI IO Packet.
+ //
+ CallerEvent = PassData->Data2;
+ gBS->CloseEvent(Event);
+ gBS->SignalEvent(CallerEvent);
+}
+
diff --git a/roms/edk2/MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBus.h b/roms/edk2/MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBus.h
new file mode 100644
index 000000000..97581866b
--- /dev/null
+++ b/roms/edk2/MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBus.h
@@ -0,0 +1,486 @@
+/** @file
+ Header file for SCSI Bus Driver.
+
+Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _SCSI_BUS_H_
+#define _SCSI_BUS_H_
+
+
+#include <Uefi.h>
+
+#include <Protocol/ScsiPassThru.h>
+#include <Protocol/ScsiPassThruExt.h>
+#include <Protocol/ScsiIo.h>
+#include <Protocol/ComponentName.h>
+#include <Protocol/DriverBinding.h>
+#include <Protocol/DevicePath.h>
+
+#include <Library/DebugLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiScsiLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/ReportStatusCodeLib.h>
+
+#include <IndustryStandard/Scsi.h>
+
+#define SCSI_IO_DEV_SIGNATURE SIGNATURE_32 ('s', 'c', 'i', 'o')
+
+typedef union {
+ UINT32 Scsi;
+ UINT8 ExtScsi[4];
+} SCSI_ID;
+
+typedef struct _SCSI_TARGET_ID {
+ SCSI_ID ScsiId;
+ UINT8 ExtScsiId[12];
+}SCSI_TARGET_ID;
+
+
+typedef struct {
+ VOID *Data1;
+ VOID *Data2;
+} SCSI_EVENT_DATA;
+
+//
+// SCSI Bus Controller device structure
+//
+#define SCSI_BUS_DEVICE_SIGNATURE SIGNATURE_32 ('s', 'c', 's', 'i')
+
+//
+// SCSI Bus Timeout Experience Value
+//
+#define SCSI_BUS_TIMEOUT EFI_TIMER_PERIOD_SECONDS (3)
+
+//
+// The ScsiBusProtocol is just used to locate ScsiBusDev
+// structure in the SCSIBusDriverBindingStop(). Then we can
+// Close all opened protocols and release this structure.
+// ScsiBusProtocol is the private protocol.
+// gEfiCallerIdGuid will be used as its protocol guid.
+//
+typedef struct _EFI_SCSI_BUS_PROTOCOL {
+ UINT64 Reserved;
+} EFI_SCSI_BUS_PROTOCOL;
+
+typedef struct _SCSI_BUS_DEVICE {
+ UINTN Signature;
+ EFI_SCSI_BUS_PROTOCOL BusIdentify;
+ BOOLEAN ExtScsiSupport;
+ EFI_SCSI_PASS_THRU_PROTOCOL *ScsiInterface;
+ EFI_EXT_SCSI_PASS_THRU_PROTOCOL *ExtScsiInterface;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+} SCSI_BUS_DEVICE;
+
+#define SCSI_BUS_CONTROLLER_DEVICE_FROM_THIS(a) CR (a, SCSI_BUS_DEVICE, BusIdentify, SCSI_BUS_DEVICE_SIGNATURE)
+
+typedef struct {
+ UINT32 Signature;
+ EFI_HANDLE Handle;
+ EFI_SCSI_IO_PROTOCOL ScsiIo;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ BOOLEAN ExtScsiSupport;
+ EFI_SCSI_PASS_THRU_PROTOCOL *ScsiPassThru;
+ EFI_EXT_SCSI_PASS_THRU_PROTOCOL *ExtScsiPassThru;
+ SCSI_BUS_DEVICE *ScsiBusDeviceData;
+ SCSI_TARGET_ID Pun;
+ UINT64 Lun;
+ UINT8 ScsiDeviceType;
+ UINT8 ScsiVersion;
+ BOOLEAN RemovableDevice;
+} SCSI_IO_DEV;
+
+#define SCSI_IO_DEV_FROM_THIS(a) CR (a, SCSI_IO_DEV, ScsiIo, SCSI_IO_DEV_SIGNATURE)
+
+//
+// Global Variables
+//
+extern EFI_DRIVER_BINDING_PROTOCOL gScsiBusDriverBinding;
+extern EFI_COMPONENT_NAME_PROTOCOL gScsiBusComponentName;
+extern EFI_COMPONENT_NAME2_PROTOCOL gScsiBusComponentName2;
+
+/**
+ Test to see if this driver supports ControllerHandle.
+
+ This service is called by the EFI boot service ConnectController(). In order
+ to make drivers as small as possible, there are a few calling restrictions for
+ this service. ConnectController() must follow these calling restrictions. If
+ any other agent wishes to call Supported() it must also follow these calling
+ restrictions.
+
+ @param This Protocol instance pointer.
+ @param ControllerHandle Handle of device to test
+ @param RemainingDevicePath Optional parameter use to pick a specific child
+ device to start.
+
+ @retval EFI_SUCCESS This driver supports this device
+ @retval EFI_ALREADY_STARTED This driver is already running on this device
+ @retval other This driver does not support this device
+
+**/
+EFI_STATUS
+EFIAPI
+SCSIBusDriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ );
+
+/**
+ Start this driver on ControllerHandle.
+
+ This service is called by the EFI boot service ConnectController(). In order
+ to make drivers as small as possible, there are a few calling restrictions for
+ this service. ConnectController() must follow these calling restrictions. If
+ any other agent wishes to call Start() it must also follow these calling
+ restrictions.
+
+ @param This Protocol instance pointer.
+ @param ControllerHandle Handle of device to bind driver to
+ @param RemainingDevicePath Optional parameter use to pick a specific child
+ device to start.
+
+ @retval EFI_SUCCESS This driver is added to ControllerHandle
+ @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle
+ @retval other This driver does not support this device
+
+**/
+EFI_STATUS
+EFIAPI
+SCSIBusDriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ );
+
+/**
+ Stop this driver on ControllerHandle.
+
+ This service is called by the EFI boot service DisconnectController().
+ In order to make drivers as small as possible, there are a few calling
+ restrictions for this service. DisconnectController() must follow these
+ calling restrictions. If any other agent wishes to call Stop() it must also
+ follow these calling restrictions.
+
+ @param This Protocol instance pointer.
+ @param ControllerHandle Handle of device to stop driver on
+ @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
+ children is zero stop the entire bus driver.
+ @param ChildHandleBuffer List of Child Handles to Stop.
+
+ @retval EFI_SUCCESS This driver is removed ControllerHandle
+ @retval other This driver was not removed from this device
+
+**/
+EFI_STATUS
+EFIAPI
+SCSIBusDriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ );
+
+//
+// EFI Component Name Functions
+//
+/**
+ Retrieves a Unicode string that is the user readable name of the driver.
+
+ This function retrieves the user readable name of a driver in the form of a
+ Unicode string. If the driver specified by This has a user readable name in
+ the language specified by Language, then a pointer to the driver name is
+ returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
+ by This does not support the language specified by Language,
+ then EFI_UNSUPPORTED is returned.
+
+ @param This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param Language A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified
+ in RFC 4646 or ISO 639-2 language code format.
+
+ @param DriverName 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
+ScsiBusComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ );
+
+/**
+ Retrieves a Unicode string that is the user readable name of the controller
+ that is being managed by a driver.
+
+ This function retrieves the user readable name of the controller specified by
+ ControllerHandle and ChildHandle in the form of a Unicode string. If the
+ driver specified by This has a user readable name in the language specified by
+ Language, then a pointer to the controller name is returned in ControllerName,
+ and EFI_SUCCESS is returned. If the driver specified by This is not currently
+ managing the controller specified by ControllerHandle and ChildHandle,
+ then EFI_UNSUPPORTED is returned. If the driver specified by This does not
+ support the language specified by Language, then EFI_UNSUPPORTED is returned.
+
+ @param This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ 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 Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified in
+ RFC 4646 or ISO 639-2 language code format.
+
+ @param ControllerName 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
+ScsiBusComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ );
+
+/**
+ Retrieves the device type information of the SCSI Controller.
+
+ @param This Protocol instance pointer.
+ @param DeviceType A pointer to the device type information retrieved from
+ the SCSI Controller.
+
+ @retval EFI_SUCCESS Retrieves the device type information successfully.
+ @retval EFI_INVALID_PARAMETER The DeviceType is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+ScsiGetDeviceType (
+ IN EFI_SCSI_IO_PROTOCOL *This,
+ OUT UINT8 *DeviceType
+ );
+
+/**
+ Retrieves the device location in the SCSI channel.
+
+ @param This Protocol instance pointer.
+ @param Target A pointer to the Target ID of a SCSI device
+ on the SCSI channel.
+ @param Lun A pointer to the LUN of the SCSI device on
+ the SCSI channel.
+
+ @retval EFI_SUCCESS Retrieves the device location successfully.
+ @retval EFI_INVALID_PARAMETER The Target or Lun is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+ScsiGetDeviceLocation (
+ IN EFI_SCSI_IO_PROTOCOL *This,
+ IN OUT UINT8 **Target,
+ OUT UINT64 *Lun
+ );
+
+/**
+ Resets the SCSI Bus that the SCSI Controller is attached to.
+
+ @param This Protocol instance pointer.
+
+ @retval EFI_SUCCESS The SCSI bus is reset successfully.
+ @retval EFI_DEVICE_ERROR Errors encountered when resetting the SCSI bus.
+ @retval EFI_UNSUPPORTED The bus reset operation is not supported by the
+ SCSI Host Controller.
+ @retval EFI_TIMEOUT A timeout occurred while attempting to reset
+ the SCSI bus.
+**/
+EFI_STATUS
+EFIAPI
+ScsiResetBus (
+ IN EFI_SCSI_IO_PROTOCOL *This
+ );
+
+/**
+ Resets the SCSI Controller that the device handle specifies.
+
+ @param This Protocol instance pointer.
+
+ @retval EFI_SUCCESS Reset the SCSI controller successfully.
+ @retval EFI_DEVICE_ERROR Errors are encountered when resetting the SCSI Controller.
+ @retval EFI_UNSUPPORTED The SCSI bus does not support a device reset operation.
+ @retval EFI_TIMEOUT A timeout occurred while attempting to reset the
+ SCSI Controller.
+**/
+EFI_STATUS
+EFIAPI
+ScsiResetDevice (
+ IN EFI_SCSI_IO_PROTOCOL *This
+ );
+
+/**
+ Sends a SCSI Request Packet to the SCSI Controller for execution.
+
+ @param This Protocol instance pointer.
+ @param CommandPacket The SCSI request packet to send to the SCSI
+ Controller specified by the device handle.
+ @param Event If the SCSI bus where the SCSI device is attached
+ does not support non-blocking I/O, then Event is
+ ignored, and blocking I/O is performed.
+ If Event is NULL, then blocking I/O is performed.
+ If Event is not NULL and non-blocking I/O is
+ supported, then non-blocking I/O is performed,
+ and Event will be signaled when the SCSI Request
+ Packet completes.
+
+ @retval EFI_SUCCESS The SCSI Request Packet was sent by the host
+ successfully, and TransferLength bytes were
+ transferred to/from DataBuffer.See
+ HostAdapterStatus, TargetStatus,
+ SenseDataLength, and SenseData in that order
+ for additional status information.
+ @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed,
+ but the entire DataBuffer could not be transferred.
+ The actual number of bytes transferred is returned
+ in TransferLength. See HostAdapterStatus,
+ TargetStatus, SenseDataLength, and SenseData in
+ that order for additional status information.
+ @retval EFI_NOT_READY The SCSI Request Packet could not be sent because
+ there are too many SCSI Command Packets already
+ queued.The caller may retry again later.
+ @retval EFI_DEVICE_ERROR A device error occurred while attempting to send
+ the SCSI Request Packet. See HostAdapterStatus,
+ TargetStatus, SenseDataLength, and SenseData in
+ that order for additional status information.
+ @retval EFI_INVALID_PARAMETER The contents of CommandPacket are invalid.
+ The SCSI Request Packet was not sent, so no
+ additional status information is available.
+ @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet
+ is not supported by the SCSI initiator(i.e., SCSI
+ Host Controller). The SCSI Request Packet was not
+ sent, so no additional status information is
+ available.
+ @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI
+ Request Packet to execute. See HostAdapterStatus,
+ TargetStatus, SenseDataLength, and SenseData in
+ that order for additional status information.
+**/
+EFI_STATUS
+EFIAPI
+ScsiExecuteSCSICommand (
+ IN EFI_SCSI_IO_PROTOCOL *This,
+ IN OUT EFI_SCSI_IO_SCSI_REQUEST_PACKET *CommandPacket,
+ IN EFI_EVENT Event OPTIONAL
+ );
+
+/**
+ Scan SCSI Bus to discover the device, and attach ScsiIoProtocol to it.
+
+ @param This Protocol instance pointer
+ @param Controller Controller handle
+ @param TargetId Target to be scanned
+ @param Lun The Lun of the SCSI device on the SCSI channel.
+ @param ScsiBusDev The pointer of SCSI_BUS_DEVICE
+
+ @retval EFI_SUCCESS Successfully to discover the device and attach
+ ScsiIoProtocol to it.
+ @retval EFI_OUT_OF_RESOURCES Fail to discover the device.
+
+**/
+EFI_STATUS
+EFIAPI
+ScsiScanCreateDevice (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN SCSI_TARGET_ID *TargetId,
+ IN UINT64 Lun,
+ IN OUT SCSI_BUS_DEVICE *ScsiBusDev
+ );
+
+/**
+ Discovery SCSI Device
+
+ @param ScsiIoDevice The pointer of SCSI_IO_DEV
+
+ @retval TRUE Find SCSI Device and verify it.
+ @retval FALSE Unable to find SCSI Device.
+
+**/
+BOOLEAN
+DiscoverScsiDevice (
+ IN OUT SCSI_IO_DEV *ScsiIoDevice
+ );
+
+#endif
diff --git a/roms/edk2/MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBus.uni b/roms/edk2/MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBus.uni
new file mode 100644
index 000000000..e384c82ea
--- /dev/null
+++ b/roms/edk2/MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBus.uni
@@ -0,0 +1,17 @@
+// /** @file
+// The SCSI bus driver scans all SCSI devices and creates a device handle for each of them.
+//
+// Note that the driver will install the Device Path Protocol and SCSI I/O Protocol on
+// these handles.
+//
+// Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT #language en-US "Scans all SCSI devices; Creates a device handle for each device"
+
+#string STR_MODULE_DESCRIPTION #language en-US "Note that the driver will install the Device Path Protocol and SCSI I/O Protocol on these handles."
+
diff --git a/roms/edk2/MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBusDxe.inf b/roms/edk2/MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBusDxe.inf
new file mode 100644
index 000000000..807ce1320
--- /dev/null
+++ b/roms/edk2/MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBusDxe.inf
@@ -0,0 +1,64 @@
+## @file
+# The SCSI bus driver scans all SCSI devices and creates a device handle for each of them.
+# Note that the driver will install the Device Path Protocol and SCSI I/O Protocol on
+# these handles.
+#
+# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = ScsiBus
+ MODULE_UNI_FILE = ScsiBus.uni
+ FILE_GUID = 0167CCC4-D0F7-4f21-A3EF-9E64B7CDCE8B
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 1.0
+
+ ENTRY_POINT = InitializeScsiBus
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 EBC
+#
+# DRIVER_BINDING = gSCSIBusDriverBinding
+# COMPONENT_NAME = gScsiBusComponentName
+# COMPONENT_NAME2 = gScsiBusComponentName2
+#
+
+[Sources]
+ ComponentName.c
+ ScsiBus.c
+ ScsiBus.h
+
+
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+
+[LibraryClasses]
+ DevicePathLib
+ UefiBootServicesTableLib
+ UefiScsiLib
+ BaseMemoryLib
+ UefiLib
+ UefiDriverEntryPoint
+ DebugLib
+ MemoryAllocationLib
+ ReportStatusCodeLib
+
+
+[Protocols]
+ gEfiScsiIoProtocolGuid ## BY_START
+ ## TO_START
+ ## BY_START
+ gEfiDevicePathProtocolGuid
+ gEfiScsiPassThruProtocolGuid ## TO_START
+ gEfiExtScsiPassThruProtocolGuid ## TO_START
+
+[UserExtensions.TianoCore."ExtraFiles"]
+ ScsiBusExtra.uni
diff --git a/roms/edk2/MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBusExtra.uni b/roms/edk2/MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBusExtra.uni
new file mode 100644
index 000000000..df8a2019a
--- /dev/null
+++ b/roms/edk2/MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBusExtra.uni
@@ -0,0 +1,14 @@
+// /** @file
+// ScsiBus Localized Strings and Content
+//
+// Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+#string STR_PROPERTIES_MODULE_NAME
+#language en-US
+"SCSI Bus DXE Driver"
+
+