2 The entry point of IScsi driver.
4 Copyright (c) 2004 - 2015, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 #include "IScsiImpl.h"
17 EFI_DRIVER_BINDING_PROTOCOL gIScsiIp4DriverBinding
= {
18 IScsiIp4DriverBindingSupported
,
19 IScsiIp4DriverBindingStart
,
20 IScsiIp4DriverBindingStop
,
26 EFI_DRIVER_BINDING_PROTOCOL gIScsiIp6DriverBinding
= {
27 IScsiIp6DriverBindingSupported
,
28 IScsiIp6DriverBindingStart
,
29 IScsiIp6DriverBindingStop
,
35 EFI_GUID gIScsiV4PrivateGuid
= ISCSI_V4_PRIVATE_GUID
;
36 EFI_GUID gIScsiV6PrivateGuid
= ISCSI_V6_PRIVATE_GUID
;
37 ISCSI_PRIVATE_DATA
*mPrivate
= NULL
;
40 Tests to see if this driver supports the RemainingDevicePath.
42 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
43 parameter is ignored by device drivers, and is optional for bus
44 drivers. For bus drivers, if this parameter is not NULL, then
45 the bus driver must determine if the bus controller specified
46 by ControllerHandle and the child controller specified
47 by RemainingDevicePath are both supported by this
50 @retval EFI_SUCCESS The RemainingDevicePath is supported or NULL.
51 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
52 RemainingDevicePath is not supported by the driver specified by This.
55 IScsiIsDevicePathSupported (
56 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
59 EFI_DEVICE_PATH_PROTOCOL
*CurrentDevicePath
;
61 CurrentDevicePath
= RemainingDevicePath
;
62 if (CurrentDevicePath
!= NULL
) {
63 while (!IsDevicePathEnd (CurrentDevicePath
)) {
64 if ((CurrentDevicePath
->Type
== MESSAGING_DEVICE_PATH
) && (CurrentDevicePath
->SubType
== MSG_ISCSI_DP
)) {
68 CurrentDevicePath
= NextDevicePathNode (CurrentDevicePath
);
71 return EFI_UNSUPPORTED
;
78 Check whether an iSCSI HBA adapter already installs an AIP instance with
79 network boot policy matching the value specified in PcdIScsiAIPNetworkBootPolicy.
80 If yes, return EFI_SUCCESS.
82 @retval EFI_SUCCESS Found an AIP with matching network boot policy.
83 @retval EFI_NOT_FOUND AIP is unavailable or the network boot policy
91 EFI_HANDLE
*AipHandleBuffer
;
93 EFI_ADAPTER_INFORMATION_PROTOCOL
*Aip
;
94 EFI_EXT_SCSI_PASS_THRU_PROTOCOL
*ExtScsiPassThru
;
95 EFI_GUID
*InfoTypesBuffer
;
96 UINTN InfoTypeBufferCount
;
101 EFI_ADAPTER_INFO_NETWORK_BOOT
*NetworkBoot
;
103 UINT8 NetworkBootPolicy
;
106 // Check any AIP instances exist in system.
109 AipHandleBuffer
= NULL
;
110 Status
= gBS
->LocateHandleBuffer (
112 &gEfiAdapterInformationProtocolGuid
,
117 if (EFI_ERROR (Status
) || AipHandleCount
== 0) {
118 return EFI_NOT_FOUND
;
121 ASSERT (AipHandleBuffer
!= NULL
);
125 for (AipIndex
= 0; AipIndex
< AipHandleCount
; AipIndex
++) {
126 Status
= gBS
->HandleProtocol (
127 AipHandleBuffer
[AipIndex
],
128 &gEfiAdapterInformationProtocolGuid
,
131 ASSERT_EFI_ERROR (Status
);
132 ASSERT (Aip
!= NULL
);
134 Status
= gBS
->HandleProtocol (
135 AipHandleBuffer
[AipIndex
],
136 &gEfiExtScsiPassThruProtocolGuid
,
137 (VOID
*) &ExtScsiPassThru
139 if (EFI_ERROR (Status
) || ExtScsiPassThru
== NULL
) {
143 InfoTypesBuffer
= NULL
;
144 InfoTypeBufferCount
= 0;
145 Status
= Aip
->GetSupportedTypes (Aip
, &InfoTypesBuffer
, &InfoTypeBufferCount
);
146 if (EFI_ERROR (Status
) || InfoTypesBuffer
== NULL
) {
150 // Check whether the AIP instance has Network boot information block.
153 for (TypeIndex
= 0; TypeIndex
< InfoTypeBufferCount
; TypeIndex
++) {
154 if (CompareGuid (&InfoTypesBuffer
[TypeIndex
], &gEfiAdapterInfoNetworkBootGuid
)) {
160 FreePool (InfoTypesBuffer
);
166 // We now have network boot information block.
170 Status
= Aip
->GetInformation (Aip
, &gEfiAdapterInfoNetworkBootGuid
, &InfoBlock
, &InfoBlockSize
);
171 if (EFI_ERROR (Status
) || InfoBlock
== NULL
) {
176 // Check whether the network boot policy matches.
178 NetworkBoot
= (EFI_ADAPTER_INFO_NETWORK_BOOT
*) InfoBlock
;
179 NetworkBootPolicy
= PcdGet8 (PcdIScsiAIPNetworkBootPolicy
);
181 if (NetworkBootPolicy
== STOP_UEFI_ISCSI_IF_HBA_INSTALL_AIP
) {
182 Status
= EFI_SUCCESS
;
185 if (((NetworkBootPolicy
& STOP_UEFI_ISCSI_IF_AIP_SUPPORT_IP4
) != 0 &&
186 !NetworkBoot
->iScsiIpv4BootCapablity
) ||
187 ((NetworkBootPolicy
& STOP_UEFI_ISCSI_IF_AIP_SUPPORT_IP6
) != 0 &&
188 !NetworkBoot
->iScsiIpv6BootCapablity
) ||
189 ((NetworkBootPolicy
& STOP_UEFI_ISCSI_IF_AIP_SUPPORT_OFFLOAD
) != 0 &&
190 !NetworkBoot
->OffloadCapability
) ||
191 ((NetworkBootPolicy
& STOP_UEFI_ISCSI_IF_AIP_SUPPORT_MPIO
) != 0 &&
192 !NetworkBoot
->iScsiMpioCapability
) ||
193 ((NetworkBootPolicy
& STOP_UEFI_ISCSI_IF_AIP_CONFIGURED_IP4
) != 0 &&
194 !NetworkBoot
->iScsiIpv4Boot
) ||
195 ((NetworkBootPolicy
& STOP_UEFI_ISCSI_IF_AIP_CONFIGURED_IP6
) != 0 &&
196 !NetworkBoot
->iScsiIpv6Boot
)) {
197 FreePool (InfoBlock
);
201 Status
= EFI_SUCCESS
;
205 Status
= EFI_NOT_FOUND
;
208 if (InfoBlock
!= NULL
) {
209 FreePool (InfoBlock
);
211 if (AipHandleBuffer
!= NULL
) {
212 FreePool (AipHandleBuffer
);
218 Tests to see if this driver supports a given controller. This is the worker function for
219 IScsiIp4(6)DriverBindingSupported.
221 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
222 @param[in] ControllerHandle The handle of the controller to test. This handle
223 must support a protocol interface that supplies
224 an I/O abstraction to the driver.
225 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
226 parameter is ignored by device drivers, and is optional for bus
227 drivers. For bus drivers, if this parameter is not NULL, then
228 the bus driver must determine if the bus controller specified
229 by ControllerHandle and the child controller specified
230 by RemainingDevicePath are both supported by this
232 @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6.
234 @retval EFI_SUCCESS The device specified by ControllerHandle and
235 RemainingDevicePath is supported by the driver specified by This.
236 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
237 RemainingDevicePath is already being managed by the driver
239 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
240 RemainingDevicePath is not supported by the driver specified by This.
245 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
246 IN EFI_HANDLE ControllerHandle
,
247 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
,
252 EFI_GUID
*IScsiServiceBindingGuid
;
253 EFI_GUID
*TcpServiceBindingGuid
;
254 EFI_GUID
*DhcpServiceBindingGuid
;
256 if (IpVersion
== IP_VERSION_4
) {
257 IScsiServiceBindingGuid
= &gIScsiV4PrivateGuid
;
258 TcpServiceBindingGuid
= &gEfiTcp4ServiceBindingProtocolGuid
;
259 DhcpServiceBindingGuid
= &gEfiDhcp4ServiceBindingProtocolGuid
;
261 IScsiServiceBindingGuid
= &gIScsiV6PrivateGuid
;
262 TcpServiceBindingGuid
= &gEfiTcp6ServiceBindingProtocolGuid
;
263 DhcpServiceBindingGuid
= &gEfiDhcp6ServiceBindingProtocolGuid
;
266 Status
= gBS
->OpenProtocol (
268 IScsiServiceBindingGuid
,
270 This
->DriverBindingHandle
,
272 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
274 if (!EFI_ERROR (Status
)) {
275 return EFI_ALREADY_STARTED
;
278 Status
= gBS
->OpenProtocol (
280 TcpServiceBindingGuid
,
282 This
->DriverBindingHandle
,
284 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
286 if (EFI_ERROR (Status
)) {
287 return EFI_UNSUPPORTED
;
290 Status
= IScsiIsDevicePathSupported (RemainingDevicePath
);
291 if (EFI_ERROR (Status
)) {
292 return EFI_UNSUPPORTED
;
295 if (IScsiDhcpIsConfigured (ControllerHandle
, IpVersion
)) {
296 Status
= gBS
->OpenProtocol (
298 DhcpServiceBindingGuid
,
300 This
->DriverBindingHandle
,
302 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
304 if (EFI_ERROR (Status
)) {
305 return EFI_UNSUPPORTED
;
314 Start to manage the controller. This is the worker function for
315 IScsiIp4(6)DriverBindingStart.
317 @param[in] Image Handle of the image.
318 @param[in] ControllerHandle Handle of the controller.
319 @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6.
321 @retval EFI_SUCCES This driver was started.
322 @retval EFI_ALREADY_STARTED This driver is already running on this device.
323 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
324 @retval EFI_NOT_FOUND There is no sufficient information to establish
326 @retval EFI_DEVICE_ERROR Failed to get TCP connection device path.
332 IN EFI_HANDLE ControllerHandle
,
337 ISCSI_DRIVER_DATA
*Private
;
339 LIST_ENTRY
*NextEntry
;
340 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
341 ISCSI_SESSION
*Session
;
343 EFI_EXT_SCSI_PASS_THRU_PROTOCOL
*ExistIScsiExtScsiPassThru
;
344 ISCSI_DRIVER_DATA
*ExistPrivate
;
345 UINT8
*AttemptConfigOrder
;
346 UINTN AttemptConfigOrderSize
;
348 EFI_HANDLE
*HandleBuffer
;
349 UINTN NumberOfHandles
;
350 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
351 EFI_GUID
*IScsiPrivateGuid
;
352 EFI_GUID
*TcpServiceBindingGuid
;
353 CHAR16 MacString
[ISCSI_MAX_MAC_STRING_LEN
];
356 EFI_GUID
*ProtocolGuid
;
357 UINT8 NetworkBootPolicy
;
360 // Test to see if iSCSI driver supports the given controller.
363 if (IpVersion
== IP_VERSION_4
) {
364 IScsiPrivateGuid
= &gIScsiV4PrivateGuid
;
365 TcpServiceBindingGuid
= &gEfiTcp4ServiceBindingProtocolGuid
;
366 ProtocolGuid
= &gEfiTcp4ProtocolGuid
;
367 } else if (IpVersion
== IP_VERSION_6
) {
368 IScsiPrivateGuid
= &gIScsiV6PrivateGuid
;
369 TcpServiceBindingGuid
= &gEfiTcp6ServiceBindingProtocolGuid
;
370 ProtocolGuid
= &gEfiTcp6ProtocolGuid
;
372 return EFI_INVALID_PARAMETER
;
375 Status
= gBS
->OpenProtocol (
381 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
383 if (!EFI_ERROR (Status
)) {
384 return EFI_ALREADY_STARTED
;
387 Status
= gBS
->OpenProtocol (
389 TcpServiceBindingGuid
,
393 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
395 if (EFI_ERROR (Status
)) {
396 return EFI_UNSUPPORTED
;
399 NetworkBootPolicy
= PcdGet8 (PcdIScsiAIPNetworkBootPolicy
);
400 if (NetworkBootPolicy
!= ALWAYS_USE_UEFI_ISCSI_AND_IGNORE_AIP
) {
402 // Check existing iSCSI AIP.
404 Status
= IScsiCheckAip ();
405 if (!EFI_ERROR (Status
)) {
407 // Find iSCSI AIP with specified network boot policy. return EFI_ABORTED.
414 // Record the incoming NIC info.
416 Status
= IScsiAddNic (ControllerHandle
);
417 if (EFI_ERROR (Status
)) {
422 // Create the instance private data.
424 Private
= IScsiCreateDriverData (Image
, ControllerHandle
);
425 if (Private
== NULL
) {
426 return EFI_OUT_OF_RESOURCES
;
430 // Create a underlayer child instance, but not need to configure it. Just open ChildHandle
431 // via BY_DRIVER. That is, establishing the relationship between ControllerHandle and ChildHandle.
432 // Therefore, when DisconnectController(), especially VLAN virtual controller handle,
433 // IScsiDriverBindingStop() will be called.
435 Status
= NetLibCreateServiceChild (
438 TcpServiceBindingGuid
,
439 &Private
->ChildHandle
442 if (EFI_ERROR (Status
)) {
446 Status
= gBS
->OpenProtocol (
447 Private
->ChildHandle
, /// Default Tcp child
452 EFI_OPEN_PROTOCOL_BY_DRIVER
455 if (EFI_ERROR (Status
)) {
460 // Always install private protocol no matter what happens later. We need to
461 // keep the relationship between ControllerHandle and ChildHandle.
463 Status
= gBS
->InstallProtocolInterface (
466 EFI_NATIVE_INTERFACE
,
467 &Private
->IScsiIdentifier
469 if (EFI_ERROR (Status
)) {
473 if (IpVersion
== IP_VERSION_4
) {
474 mPrivate
->Ipv6Flag
= FALSE
;
476 mPrivate
->Ipv6Flag
= TRUE
;
480 // Get the current iSCSI configuration data.
482 Status
= IScsiGetConfigData (Private
);
483 if (EFI_ERROR (Status
)) {
488 // If there is already a successul attempt, check whether this attempt is the
489 // first "enabled for MPIO" attempt. If not, still try the first attempt.
490 // In single path mode, try all attempts.
493 Status
= EFI_NOT_FOUND
;
495 if (mPrivate
->OneSessionEstablished
&& mPrivate
->EnableMpio
) {
496 AttemptConfigData
= NULL
;
497 NET_LIST_FOR_EACH (Entry
, &mPrivate
->AttemptConfigs
) {
498 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
499 if (AttemptConfigData
->SessionConfigData
.Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
504 if (AttemptConfigData
== NULL
) {
508 if (AttemptConfigData
->AttemptConfigIndex
== mPrivate
->BootSelectedIndex
) {
513 // Uninstall the original ExtScsiPassThru first.
517 // Locate all ExtScsiPassThru protocol instances.
519 Status
= gBS
->LocateHandleBuffer (
521 &gEfiExtScsiPassThruProtocolGuid
,
526 if (EFI_ERROR (Status
)) {
531 // Find ExtScsiPassThru protocol instance produced by this driver.
533 ExistIScsiExtScsiPassThru
= NULL
;
534 for (Index
= 0; Index
< NumberOfHandles
&& ExistIScsiExtScsiPassThru
== NULL
; Index
++) {
535 Status
= gBS
->HandleProtocol (
537 &gEfiDevicePathProtocolGuid
,
538 (VOID
**) &DevicePath
540 if (EFI_ERROR (Status
)) {
544 while (!IsDevicePathEnd (DevicePath
)) {
545 if ((DevicePath
->Type
== MESSAGING_DEVICE_PATH
) && (DevicePath
->SubType
== MSG_MAC_ADDR_DP
)) {
547 // Get the ExtScsiPassThru protocol instance.
549 Status
= gBS
->HandleProtocol (
551 &gEfiExtScsiPassThruProtocolGuid
,
552 (VOID
**) &ExistIScsiExtScsiPassThru
554 ASSERT_EFI_ERROR (Status
);
558 DevicePath
= NextDevicePathNode (DevicePath
);
562 FreePool (HandleBuffer
);
564 if (ExistIScsiExtScsiPassThru
== NULL
) {
565 Status
= EFI_NOT_FOUND
;
569 ExistPrivate
= ISCSI_DRIVER_DATA_FROM_EXT_SCSI_PASS_THRU (ExistIScsiExtScsiPassThru
);
571 Status
= gBS
->UninstallProtocolInterface (
572 ExistPrivate
->ExtScsiPassThruHandle
,
573 &gEfiExtScsiPassThruProtocolGuid
,
574 &ExistPrivate
->IScsiExtScsiPassThru
576 if (EFI_ERROR (Status
)) {
582 // Install the Ext SCSI PASS THRU protocol.
584 Status
= gBS
->InstallProtocolInterface (
585 &Private
->ExtScsiPassThruHandle
,
586 &gEfiExtScsiPassThruProtocolGuid
,
587 EFI_NATIVE_INTERFACE
,
588 &Private
->IScsiExtScsiPassThru
590 if (EFI_ERROR (Status
)) {
596 NET_LIST_FOR_EACH_SAFE (Entry
, NextEntry
, &mPrivate
->AttemptConfigs
) {
597 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
599 // Don't process the attempt that does not associate with the current NIC or
600 // this attempt is disabled or established.
602 if (AttemptConfigData
->NicIndex
!= mPrivate
->CurrentNic
||
603 AttemptConfigData
->SessionConfigData
.Enabled
== ISCSI_DISABLED
||
604 AttemptConfigData
->ValidPath
) {
609 // In multipath mode, don't process attempts configured for single path.
610 // In default single path mode, don't process attempts configured for multipath.
612 if ((mPrivate
->EnableMpio
&&
613 AttemptConfigData
->SessionConfigData
.Enabled
!= ISCSI_ENABLED_FOR_MPIO
) ||
614 (!mPrivate
->EnableMpio
&&
615 AttemptConfigData
->SessionConfigData
.Enabled
!= ISCSI_ENABLED
)) {
620 // Don't process the attempt that fails to get the init/target information from DHCP.
622 if (AttemptConfigData
->SessionConfigData
.InitiatorInfoFromDhcp
&&
623 !AttemptConfigData
->DhcpSuccess
) {
624 if (!mPrivate
->EnableMpio
&& mPrivate
->ValidSinglePathCount
> 0) {
625 mPrivate
->ValidSinglePathCount
--;
631 // Don't process the autoconfigure path if it is already established.
633 if (AttemptConfigData
->SessionConfigData
.IpMode
== IP_MODE_AUTOCONFIG
&&
634 AttemptConfigData
->AutoConfigureSuccess
) {
639 // Don't process the attempt if its IP mode is not in the current IP version.
641 if (!mPrivate
->Ipv6Flag
) {
642 if (AttemptConfigData
->SessionConfigData
.IpMode
== IP_MODE_IP6
) {
645 if (AttemptConfigData
->SessionConfigData
.IpMode
== IP_MODE_AUTOCONFIG
&&
646 AttemptConfigData
->AutoConfigureMode
== IP_MODE_AUTOCONFIG_IP6
) {
650 if (AttemptConfigData
->SessionConfigData
.IpMode
== IP_MODE_IP4
) {
653 if (AttemptConfigData
->SessionConfigData
.IpMode
== IP_MODE_AUTOCONFIG
&&
654 AttemptConfigData
->AutoConfigureMode
== IP_MODE_AUTOCONFIG_IP4
) {
660 // Fill in the Session and init it.
662 Session
= (ISCSI_SESSION
*) AllocateZeroPool (sizeof (ISCSI_SESSION
));
663 if (Session
== NULL
) {
664 Status
= EFI_OUT_OF_RESOURCES
;
668 Session
->Private
= Private
;
669 Session
->ConfigData
= AttemptConfigData
;
670 Session
->AuthType
= AttemptConfigData
->AuthenticationType
;
672 AsciiStrToUnicodeStr (AttemptConfigData
->MacString
, MacString
);
674 mPrivate
->PortString
,
675 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
678 (UINTN
) AttemptConfigData
->AttemptConfigIndex
681 if (Session
->AuthType
== ISCSI_AUTH_TYPE_CHAP
) {
682 Session
->AuthData
.CHAP
.AuthConfig
= &AttemptConfigData
->AuthConfigData
.CHAP
;
685 IScsiSessionInit (Session
, FALSE
);
688 // Try to login and create an iSCSI session according to the configuration.
690 Status
= IScsiSessionLogin (Session
);
691 if (Status
== EFI_MEDIA_CHANGED
) {
693 // The specified target is not available, and the redirection information is
694 // received. Login the session again with the updated target address.
696 Status
= IScsiSessionLogin (Session
);
697 } else if (Status
== EFI_NOT_READY
) {
698 Status
= IScsiSessionReLogin (Session
);
701 if (EFI_ERROR (Status
)) {
703 // In Single path mode, only the successful attempt will be recorded in iBFT;
704 // in multi-path mode, all the attempt entries in MPIO will be recorded in iBFT.
706 if (!mPrivate
->EnableMpio
&& mPrivate
->ValidSinglePathCount
> 0) {
707 mPrivate
->ValidSinglePathCount
--;
713 AttemptConfigData
->ValidPath
= TRUE
;
716 // Do not record the attempt in iBFT if it login with KRB5.
717 // TODO: record KRB5 attempt information in the iSCSI device path.
719 if (Session
->AuthType
== ISCSI_AUTH_TYPE_KRB
) {
720 if (!mPrivate
->EnableMpio
&& mPrivate
->ValidSinglePathCount
> 0) {
721 mPrivate
->ValidSinglePathCount
--;
724 AttemptConfigData
->ValidiBFTPath
= FALSE
;
726 AttemptConfigData
->ValidiBFTPath
= TRUE
;
730 // IScsi session success. Update the attempt state to NVR.
732 if (AttemptConfigData
->SessionConfigData
.IpMode
== IP_MODE_AUTOCONFIG
) {
733 AttemptConfigData
->AutoConfigureSuccess
= TRUE
;
737 mPrivate
->PortString
,
738 &gEfiIScsiInitiatorNameProtocolGuid
,
739 ISCSI_CONFIG_VAR_ATTR
,
740 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA
),
745 // Select the first login session. Abort others.
747 if (Private
->Session
== NULL
) {
748 Private
->Session
= Session
;
749 BootSelected
= AttemptConfigData
->AttemptConfigIndex
;
751 // Don't validate other attempt in multipath mode if one is success.
753 if (mPrivate
->EnableMpio
) {
757 IScsiSessionAbort (Session
);
764 // All attempts configured for this driver instance are not valid.
766 if (Private
->Session
== NULL
) {
767 Status
= gBS
->UninstallProtocolInterface (
768 Private
->ExtScsiPassThruHandle
,
769 &gEfiExtScsiPassThruProtocolGuid
,
770 &Private
->IScsiExtScsiPassThru
772 ASSERT_EFI_ERROR (Status
);
773 Private
->ExtScsiPassThruHandle
= NULL
;
776 // Reinstall the original ExtScsiPassThru back.
778 if (mPrivate
->OneSessionEstablished
&& ExistPrivate
!= NULL
) {
779 Status
= gBS
->InstallProtocolInterface (
780 &ExistPrivate
->ExtScsiPassThruHandle
,
781 &gEfiExtScsiPassThruProtocolGuid
,
782 EFI_NATIVE_INTERFACE
,
783 &ExistPrivate
->IScsiExtScsiPassThru
785 if (EFI_ERROR (Status
)) {
792 Status
= EFI_NOT_FOUND
;
799 // More than one attempt successes.
801 if (Private
->Session
!= NULL
&& mPrivate
->OneSessionEstablished
) {
803 AttemptConfigOrder
= IScsiGetVariableAndSize (
806 &AttemptConfigOrderSize
808 if (AttemptConfigOrder
== NULL
) {
811 for (Index
= 0; Index
< AttemptConfigOrderSize
/ sizeof (UINT8
); Index
++) {
812 if (AttemptConfigOrder
[Index
] == mPrivate
->BootSelectedIndex
||
813 AttemptConfigOrder
[Index
] == BootSelected
) {
818 if (mPrivate
->EnableMpio
) {
820 // Use the attempt in earlier order. Abort the later one in MPIO.
822 if (AttemptConfigOrder
[Index
] == mPrivate
->BootSelectedIndex
) {
823 IScsiSessionAbort (Private
->Session
);
824 FreePool (Private
->Session
);
825 Private
->Session
= NULL
;
826 gBS
->UninstallProtocolInterface (
827 Private
->ExtScsiPassThruHandle
,
828 &gEfiExtScsiPassThruProtocolGuid
,
829 &Private
->IScsiExtScsiPassThru
831 Private
->ExtScsiPassThruHandle
= NULL
;
834 // Reinstall the original ExtScsiPassThru back.
836 Status
= gBS
->InstallProtocolInterface (
837 &ExistPrivate
->ExtScsiPassThruHandle
,
838 &gEfiExtScsiPassThruProtocolGuid
,
839 EFI_NATIVE_INTERFACE
,
840 &ExistPrivate
->IScsiExtScsiPassThru
842 if (EFI_ERROR (Status
)) {
848 if (AttemptConfigOrder
[Index
] != BootSelected
) {
851 mPrivate
->BootSelectedIndex
= BootSelected
;
853 // Clear the resource in ExistPrivate.
855 gBS
->UninstallProtocolInterface (
856 ExistPrivate
->Controller
,
858 &ExistPrivate
->IScsiIdentifier
861 IScsiRemoveNic (ExistPrivate
->Controller
);
862 if (ExistPrivate
->Session
!= NULL
) {
863 IScsiSessionAbort (ExistPrivate
->Session
);
866 IScsiCleanDriverData (ExistPrivate
);
870 // Use the attempt in earlier order as boot selected in single path mode.
872 if (AttemptConfigOrder
[Index
] == mPrivate
->BootSelectedIndex
) {
880 mPrivate
->OneSessionEstablished
= TRUE
;
881 mPrivate
->BootSelectedIndex
= BootSelected
;
885 // Duplicate the Session's tcp connection device path. The source port field
886 // will be set to zero as one iSCSI session is comprised of several iSCSI
889 Private
->DevicePath
= IScsiGetTcpConnDevicePath (Private
->Session
);
890 if (Private
->DevicePath
== NULL
) {
891 Status
= EFI_DEVICE_ERROR
;
895 // Install the updated device path onto the ExtScsiPassThruHandle.
897 Status
= gBS
->InstallProtocolInterface (
898 &Private
->ExtScsiPassThruHandle
,
899 &gEfiDevicePathProtocolGuid
,
900 EFI_NATIVE_INTERFACE
,
903 if (EFI_ERROR (Status
)) {
908 // ISCSI children should share the default Tcp child, just open the default Tcp child via BY_CHILD_CONTROLLER.
910 Status
= gBS
->OpenProtocol (
911 Private
->ChildHandle
, /// Default Tcp child
915 Private
->ExtScsiPassThruHandle
,
916 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
918 if (EFI_ERROR (Status
)) {
919 gBS
->UninstallMultipleProtocolInterfaces (
920 Private
->ExtScsiPassThruHandle
,
921 &gEfiExtScsiPassThruProtocolGuid
,
922 &Private
->IScsiExtScsiPassThru
,
923 &gEfiDevicePathProtocolGuid
,
934 // Update/Publish the iSCSI Boot Firmware Table.
936 if (mPrivate
->BootSelectedIndex
!= 0) {
944 if (Private
->Session
!= NULL
) {
945 IScsiSessionAbort (Private
->Session
);
952 Stops a device controller or a bus controller. This is the worker function for
953 IScsiIp4(6)DriverBindingStop.
955 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
956 @param[in] ControllerHandle A handle to the device being stopped. The handle must
957 support a bus specific I/O protocol for the driver
958 to use to stop the device.
959 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
960 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
961 if NumberOfChildren is 0.
962 @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6.
964 @retval EFI_SUCCESS The device was stopped.
965 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
971 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
972 IN EFI_HANDLE ControllerHandle
,
973 IN UINTN NumberOfChildren
,
974 IN EFI_HANDLE
*ChildHandleBuffer OPTIONAL
,
978 EFI_HANDLE IScsiController
;
980 ISCSI_PRIVATE_PROTOCOL
*IScsiIdentifier
;
981 ISCSI_DRIVER_DATA
*Private
;
982 EFI_EXT_SCSI_PASS_THRU_PROTOCOL
*PassThru
;
983 ISCSI_CONNECTION
*Conn
;
984 EFI_GUID
*ProtocolGuid
;
985 EFI_GUID
*TcpServiceBindingGuid
;
986 EFI_GUID
*TcpProtocolGuid
;
989 if (NumberOfChildren
!= 0) {
991 // We should have only one child.
993 Status
= gBS
->OpenProtocol (
994 ChildHandleBuffer
[0],
995 &gEfiExtScsiPassThruProtocolGuid
,
997 This
->DriverBindingHandle
,
999 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1001 if (EFI_ERROR (Status
)) {
1002 return EFI_DEVICE_ERROR
;
1005 Private
= ISCSI_DRIVER_DATA_FROM_EXT_SCSI_PASS_THRU (PassThru
);
1006 Conn
= NET_LIST_HEAD (&Private
->Session
->Conns
, ISCSI_CONNECTION
, Link
);
1009 // Previously the TCP protocol is opened BY_CHILD_CONTROLLER. Just close
1010 // the protocol here, but do not uninstall the device path protocol and
1011 // EXT SCSI PASS THRU protocol installed on ExtScsiPassThruHandle.
1013 if (IpVersion
== IP_VERSION_4
) {
1014 ProtocolGuid
= &gEfiTcp4ProtocolGuid
;
1016 ProtocolGuid
= &gEfiTcp6ProtocolGuid
;
1019 gBS
->CloseProtocol (
1020 Private
->ChildHandle
,
1023 Private
->ExtScsiPassThruHandle
1026 gBS
->CloseProtocol (
1030 Private
->ExtScsiPassThruHandle
1037 // Get the handle of the controller we are controling.
1039 if (IpVersion
== IP_VERSION_4
) {
1040 ProtocolGuid
= &gIScsiV4PrivateGuid
;
1041 TcpProtocolGuid
= &gEfiTcp4ProtocolGuid
;
1042 TcpServiceBindingGuid
= &gEfiTcp4ServiceBindingProtocolGuid
;
1044 ProtocolGuid
= &gIScsiV6PrivateGuid
;
1045 TcpProtocolGuid
= &gEfiTcp6ProtocolGuid
;
1046 TcpServiceBindingGuid
= &gEfiTcp6ServiceBindingProtocolGuid
;
1048 IScsiController
= NetLibGetNicHandle (ControllerHandle
, TcpProtocolGuid
);
1049 if (IScsiController
== NULL
) {
1053 Status
= gBS
->OpenProtocol (
1056 (VOID
**) &IScsiIdentifier
,
1057 This
->DriverBindingHandle
,
1059 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1061 if (EFI_ERROR (Status
)) {
1062 return EFI_DEVICE_ERROR
;
1065 Private
= ISCSI_DRIVER_DATA_FROM_IDENTIFIER (IScsiIdentifier
);
1066 ASSERT (Private
!= NULL
);
1068 if (Private
->ChildHandle
!= NULL
) {
1069 Status
= gBS
->CloseProtocol (
1070 Private
->ChildHandle
,
1072 This
->DriverBindingHandle
,
1076 ASSERT (!EFI_ERROR (Status
));
1078 Status
= NetLibDestroyServiceChild (
1080 This
->DriverBindingHandle
,
1081 TcpServiceBindingGuid
,
1082 Private
->ChildHandle
1085 ASSERT (!EFI_ERROR (Status
));
1088 gBS
->UninstallProtocolInterface (
1091 &Private
->IScsiIdentifier
1097 IScsiRemoveNic (IScsiController
);
1100 // Update the iSCSI Boot Firware Table.
1102 IScsiPublishIbft ();
1104 if (Private
->Session
!= NULL
) {
1105 IScsiSessionAbort (Private
->Session
);
1108 IScsiCleanDriverData (Private
);
1114 Tests to see if this driver supports a given controller. If a child device is provided,
1115 it tests to see if this driver supports creating a handle for the specified child device.
1117 This function checks to see if the driver specified by This supports the device specified by
1118 ControllerHandle. Drivers typically use the device path attached to
1119 ControllerHandle and/or the services from the bus I/O abstraction attached to
1120 ControllerHandle to determine if the driver supports ControllerHandle. This function
1121 may be called many times during platform initialization. In order to reduce boot times, the tests
1122 performed by this function must be very small and take as little time as possible to execute. This
1123 function must not change the state of any hardware devices, and this function must be aware that the
1124 device specified by ControllerHandle may already be managed by the same driver or a
1125 different driver. This function must match its calls to AllocatePages() with FreePages(),
1126 AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
1127 Since ControllerHandle may have been previously started by the same driver, if a protocol is
1128 already in the opened state, then it must not be closed with CloseProtocol(). This is required
1129 to guarantee the state of ControllerHandle is not modified by this function.
1131 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
1132 @param[in] ControllerHandle The handle of the controller to test. This handle
1133 must support a protocol interface that supplies
1134 an I/O abstraction to the driver.
1135 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
1136 parameter is ignored by device drivers, and is optional for bus
1137 drivers. For bus drivers, if this parameter is not NULL, then
1138 the bus driver must determine if the bus controller specified
1139 by ControllerHandle and the child controller specified
1140 by RemainingDevicePath are both supported by this
1143 @retval EFI_SUCCESS The device specified by ControllerHandle and
1144 RemainingDevicePath is supported by the driver specified by This.
1145 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
1146 RemainingDevicePath is already managed by the driver
1148 @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
1149 RemainingDevicePath is already managed by a different
1150 driver or an application that requires exclusive access.
1151 Currently not implemented.
1152 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
1153 RemainingDevicePath is not supported by the driver specified by This.
1157 IScsiIp4DriverBindingSupported (
1158 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1159 IN EFI_HANDLE ControllerHandle
,
1160 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
1163 return IScsiSupported (
1166 RemainingDevicePath
,
1172 Starts a device controller or a bus controller.
1174 The Start() function is designed to be invoked from the EFI boot service ConnectController().
1175 As a result, much of the error checking on the parameters to Start() has been moved into this
1176 common boot service. It is legal to call Start() from other locations,
1177 but the following calling restrictions must be followed or the system behavior will not be deterministic.
1178 1. ControllerHandle must be a valid EFI_HANDLE.
1179 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
1180 EFI_DEVICE_PATH_PROTOCOL.
1181 3. Prior to calling Start(), the Supported() function for the driver specified by This must
1182 have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
1184 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
1185 @param[in] ControllerHandle The handle of the controller to start. This handle
1186 must support a protocol interface that supplies
1187 an I/O abstraction to the driver.
1188 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
1189 parameter is ignored by device drivers, and is optional for bus
1190 drivers. For a bus driver, if this parameter is NULL, then handles
1191 for all the children of Controller are created by this driver.
1192 If this parameter is not NULL and the first Device Path Node is
1193 not the End of Device Path Node, then only the handle for the
1194 child device specified by the first Device Path Node of
1195 RemainingDevicePath is created by this driver.
1196 If the first Device Path Node of RemainingDevicePath is
1197 the End of Device Path Node, no child handle is created by this
1200 @retval EFI_SUCCESS The device was started.
1201 @retval EFI_DEVICE_ERROR The device could not be started due to a device error. Currently not implemented.
1202 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
1203 @retval Others The driver failed to start the device.
1208 IScsiIp4DriverBindingStart (
1209 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1210 IN EFI_HANDLE ControllerHandle
,
1211 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
1216 Status
= IScsiStart (This
->DriverBindingHandle
, ControllerHandle
, IP_VERSION_4
);
1217 if (Status
== EFI_ALREADY_STARTED
) {
1218 Status
= EFI_SUCCESS
;
1225 Stops a device controller or a bus controller.
1227 The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
1228 As a result, much of the error checking on the parameters to Stop() has been moved
1229 into this common boot service. It is legal to call Stop() from other locations,
1230 but the following calling restrictions must be followed or the system behavior will not be deterministic.
1231 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
1232 same driver's Start() function.
1233 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
1234 EFI_HANDLE. In addition, all of these handles must have been created in this driver's
1235 Start() function, and the Start() function must have called OpenProtocol() on
1236 ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
1238 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
1239 @param[in] ControllerHandle A handle to the device being stopped. The handle must
1240 support a bus specific I/O protocol for the driver
1241 to use to stop the device.
1242 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
1243 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
1244 if NumberOfChildren is 0.
1246 @retval EFI_SUCCESS The device was stopped.
1247 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
1252 IScsiIp4DriverBindingStop (
1253 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1254 IN EFI_HANDLE ControllerHandle
,
1255 IN UINTN NumberOfChildren
,
1256 IN EFI_HANDLE
*ChildHandleBuffer OPTIONAL
1269 Tests to see if this driver supports a given controller. If a child device is provided,
1270 it tests to see if this driver supports creating a handle for the specified child device.
1272 This function checks to see if the driver specified by This supports the device specified by
1273 ControllerHandle. Drivers typically use the device path attached to
1274 ControllerHandle and/or the services from the bus I/O abstraction attached to
1275 ControllerHandle to determine if the driver supports ControllerHandle. This function
1276 may be called many times during platform initialization. In order to reduce boot times, the tests
1277 performed by this function must be very small and take as little time as possible to execute. This
1278 function must not change the state of any hardware devices, and this function must be aware that the
1279 device specified by ControllerHandle may already be managed by the same driver or a
1280 different driver. This function must match its calls to AllocatePages() with FreePages(),
1281 AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
1282 Since ControllerHandle may have been previously started by the same driver, if a protocol is
1283 already in the opened state, then it must not be closed with CloseProtocol(). This is required
1284 to guarantee the state of ControllerHandle is not modified by this function.
1286 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
1287 @param[in] ControllerHandle The handle of the controller to test. This handle
1288 must support a protocol interface that supplies
1289 an I/O abstraction to the driver.
1290 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
1291 parameter is ignored by device drivers, and is optional for bus
1292 drivers. For bus drivers, if this parameter is not NULL, then
1293 the bus driver must determine if the bus controller specified
1294 by ControllerHandle and the child controller specified
1295 by RemainingDevicePath are both supported by this
1298 @retval EFI_SUCCESS The device specified by ControllerHandle and
1299 RemainingDevicePath is supported by the driver specified by This.
1300 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
1301 RemainingDevicePath is already managed by the driver
1303 @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
1304 RemainingDevicePath is already managed by a different
1305 driver or an application that requires exclusive access.
1306 Currently not implemented.
1307 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
1308 RemainingDevicePath is not supported by the driver specified by This.
1312 IScsiIp6DriverBindingSupported (
1313 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1314 IN EFI_HANDLE ControllerHandle
,
1315 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
1318 return IScsiSupported (
1321 RemainingDevicePath
,
1327 Starts a device controller or a bus controller.
1329 The Start() function is designed to be invoked from the EFI boot service ConnectController().
1330 As a result, much of the error checking on the parameters to Start() has been moved into this
1331 common boot service. It is legal to call Start() from other locations,
1332 but the following calling restrictions must be followed or the system behavior will not be deterministic.
1333 1. ControllerHandle must be a valid EFI_HANDLE.
1334 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
1335 EFI_DEVICE_PATH_PROTOCOL.
1336 3. Prior to calling Start(), the Supported() function for the driver specified by This must
1337 have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
1339 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
1340 @param[in] ControllerHandle The handle of the controller to start. This handle
1341 must support a protocol interface that supplies
1342 an I/O abstraction to the driver.
1343 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
1344 parameter is ignored by device drivers, and is optional for bus
1345 drivers. For a bus driver, if this parameter is NULL, then handles
1346 for all the children of Controller are created by this driver.
1347 If this parameter is not NULL and the first Device Path Node is
1348 not the End of Device Path Node, then only the handle for the
1349 child device specified by the first Device Path Node of
1350 RemainingDevicePath is created by this driver.
1351 If the first Device Path Node of RemainingDevicePath is
1352 the End of Device Path Node, no child handle is created by this
1355 @retval EFI_SUCCESS The device was started.
1356 @retval EFI_DEVICE_ERROR The device could not be started due to a device error. Currently not implemented.
1357 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
1358 @retval Others The driver failed to start the device.
1363 IScsiIp6DriverBindingStart (
1364 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1365 IN EFI_HANDLE ControllerHandle
,
1366 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
1371 Status
= IScsiStart (This
->DriverBindingHandle
, ControllerHandle
, IP_VERSION_6
);
1372 if (Status
== EFI_ALREADY_STARTED
) {
1373 Status
= EFI_SUCCESS
;
1380 Stops a device controller or a bus controller.
1382 The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
1383 As a result, much of the error checking on the parameters to Stop() has been moved
1384 into this common boot service. It is legal to call Stop() from other locations,
1385 but the following calling restrictions must be followed or the system behavior will not be deterministic.
1386 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
1387 same driver's Start() function.
1388 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
1389 EFI_HANDLE. In addition, all of these handles must have been created in this driver's
1390 Start() function, and the Start() function must have called OpenProtocol() on
1391 ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
1393 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
1394 @param[in] ControllerHandle A handle to the device being stopped. The handle must
1395 support a bus specific I/O protocol for the driver
1396 to use to stop the device.
1397 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
1398 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
1399 if NumberOfChildren is 0.
1401 @retval EFI_SUCCESS The device was stopped.
1402 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
1407 IScsiIp6DriverBindingStop (
1408 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1409 IN EFI_HANDLE ControllerHandle
,
1410 IN UINTN NumberOfChildren
,
1411 IN EFI_HANDLE
*ChildHandleBuffer OPTIONAL
1424 Unload the iSCSI driver.
1426 @param[in] ImageHandle The handle of the driver image.
1428 @retval EFI_SUCCESS The driver is unloaded.
1429 @retval EFI_DEVICE_ERROR An unexpected error occurred.
1435 IN EFI_HANDLE ImageHandle
1439 UINTN DeviceHandleCount
;
1440 EFI_HANDLE
*DeviceHandleBuffer
;
1442 EFI_COMPONENT_NAME_PROTOCOL
*ComponentName
;
1443 EFI_COMPONENT_NAME2_PROTOCOL
*ComponentName2
;
1446 // Try to disonnect the driver from the devices it's controlling.
1448 Status
= gBS
->LocateHandleBuffer (
1455 if (EFI_ERROR (Status
)) {
1460 // Disconnect the iSCSI4 driver from the controlled device.
1462 for (Index
= 0; Index
< DeviceHandleCount
; Index
++) {
1463 Status
= IScsiTestManagedDevice (
1464 DeviceHandleBuffer
[Index
],
1465 gIScsiIp4DriverBinding
.DriverBindingHandle
,
1466 &gEfiTcp4ProtocolGuid
)
1468 if (EFI_ERROR (Status
)) {
1471 Status
= gBS
->DisconnectController (
1472 DeviceHandleBuffer
[Index
],
1473 gIScsiIp4DriverBinding
.DriverBindingHandle
,
1476 if (EFI_ERROR (Status
)) {
1482 // Disconnect the iSCSI6 driver from the controlled device.
1484 for (Index
= 0; Index
< DeviceHandleCount
; Index
++) {
1485 Status
= IScsiTestManagedDevice (
1486 DeviceHandleBuffer
[Index
],
1487 gIScsiIp6DriverBinding
.DriverBindingHandle
,
1488 &gEfiTcp6ProtocolGuid
1490 if (EFI_ERROR (Status
)) {
1493 Status
= gBS
->DisconnectController (
1494 DeviceHandleBuffer
[Index
],
1495 gIScsiIp6DriverBinding
.DriverBindingHandle
,
1498 if (EFI_ERROR (Status
)) {
1504 // Unload the iSCSI configuration form.
1506 Status
= IScsiConfigFormUnload (gIScsiIp4DriverBinding
.DriverBindingHandle
);
1507 if (EFI_ERROR (Status
)) {
1512 // Uninstall the protocols installed by iSCSI driver.
1514 Status
= gBS
->UninstallMultipleProtocolInterfaces (
1516 &gEfiAuthenticationInfoProtocolGuid
,
1517 &gIScsiAuthenticationInfo
,
1520 if (EFI_ERROR (Status
)) {
1524 if (gIScsiControllerNameTable
!= NULL
) {
1525 Status
= FreeUnicodeStringTable (gIScsiControllerNameTable
);
1526 if (EFI_ERROR (Status
)) {
1529 gIScsiControllerNameTable
= NULL
;
1533 // Uninstall the ComponentName and ComponentName2 protocol from iSCSI4 driver binding handle
1534 // if it has been installed.
1536 Status
= gBS
->HandleProtocol (
1537 gIScsiIp4DriverBinding
.DriverBindingHandle
,
1538 &gEfiComponentNameProtocolGuid
,
1539 (VOID
**) &ComponentName
1541 if (!EFI_ERROR (Status
)) {
1542 Status
= gBS
->UninstallMultipleProtocolInterfaces (
1543 gIScsiIp4DriverBinding
.DriverBindingHandle
,
1544 &gEfiComponentNameProtocolGuid
,
1548 if (EFI_ERROR (Status
)) {
1553 Status
= gBS
->HandleProtocol (
1554 gIScsiIp4DriverBinding
.DriverBindingHandle
,
1555 &gEfiComponentName2ProtocolGuid
,
1556 (VOID
**) &ComponentName2
1558 if (!EFI_ERROR (Status
)) {
1559 gBS
->UninstallMultipleProtocolInterfaces (
1560 gIScsiIp4DriverBinding
.DriverBindingHandle
,
1561 &gEfiComponentName2ProtocolGuid
,
1565 if (EFI_ERROR (Status
)) {
1571 // Uninstall the ComponentName and ComponentName2 protocol from iSCSI6 driver binding handle
1572 // if it has been installed.
1574 Status
= gBS
->HandleProtocol (
1575 gIScsiIp6DriverBinding
.DriverBindingHandle
,
1576 &gEfiComponentNameProtocolGuid
,
1577 (VOID
**) &ComponentName
1579 if (!EFI_ERROR (Status
)) {
1580 Status
= gBS
->UninstallMultipleProtocolInterfaces (
1581 gIScsiIp6DriverBinding
.DriverBindingHandle
,
1582 &gEfiComponentNameProtocolGuid
,
1586 if (EFI_ERROR (Status
)) {
1591 Status
= gBS
->HandleProtocol (
1592 gIScsiIp6DriverBinding
.DriverBindingHandle
,
1593 &gEfiComponentName2ProtocolGuid
,
1594 (VOID
**) &ComponentName2
1596 if (!EFI_ERROR (Status
)) {
1597 gBS
->UninstallMultipleProtocolInterfaces (
1598 gIScsiIp6DriverBinding
.DriverBindingHandle
,
1599 &gEfiComponentName2ProtocolGuid
,
1603 if (EFI_ERROR (Status
)) {
1609 // Uninstall the IScsiInitiatorNameProtocol and all the driver binding protocols.
1611 Status
= gBS
->UninstallMultipleProtocolInterfaces (
1612 gIScsiIp4DriverBinding
.DriverBindingHandle
,
1613 &gEfiDriverBindingProtocolGuid
,
1614 &gIScsiIp4DriverBinding
,
1615 &gEfiIScsiInitiatorNameProtocolGuid
,
1616 &gIScsiInitiatorName
,
1619 if (EFI_ERROR (Status
)) {
1623 Status
= gBS
->UninstallMultipleProtocolInterfaces (
1624 gIScsiIp6DriverBinding
.DriverBindingHandle
,
1625 &gEfiDriverBindingProtocolGuid
,
1626 &gIScsiIp6DriverBinding
,
1632 if (DeviceHandleBuffer
!= NULL
) {
1633 FreePool (DeviceHandleBuffer
);
1640 This is the declaration of an EFI image entry point. This entry point is
1641 the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including
1642 both device drivers and bus drivers.
1644 The entry point for iSCSI driver which initializes the global variables and
1645 installs the driver binding, component name protocol, iSCSI initiator name
1646 protocol and Authentication Info protocol on its image.
1648 @param[in] ImageHandle The firmware allocated handle for the UEFI image.
1649 @param[in] SystemTable A pointer to the EFI System Table.
1651 @retval EFI_SUCCESS The operation completed successfully.
1652 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
1657 IScsiDriverEntryPoint (
1658 IN EFI_HANDLE ImageHandle
,
1659 IN EFI_SYSTEM_TABLE
*SystemTable
1663 EFI_ISCSI_INITIATOR_NAME_PROTOCOL
*IScsiInitiatorName
;
1664 EFI_AUTHENTICATION_INFO_PROTOCOL
*AuthenticationInfo
;
1667 // There should be only one EFI_ISCSI_INITIATOR_NAME_PROTOCOL.
1669 Status
= gBS
->LocateProtocol (
1670 &gEfiIScsiInitiatorNameProtocolGuid
,
1672 (VOID
**) &IScsiInitiatorName
1674 if (!EFI_ERROR (Status
)) {
1675 return EFI_ACCESS_DENIED
;
1679 // Initialize the EFI Driver Library.
1681 Status
= EfiLibInstallDriverBindingComponentName2 (
1684 &gIScsiIp4DriverBinding
,
1686 &gIScsiComponentName
,
1687 &gIScsiComponentName2
1689 if (EFI_ERROR (Status
)) {
1693 Status
= EfiLibInstallDriverBindingComponentName2 (
1696 &gIScsiIp6DriverBinding
,
1698 &gIScsiComponentName
,
1699 &gIScsiComponentName2
1701 if (EFI_ERROR (Status
)) {
1706 // Install the iSCSI Initiator Name Protocol.
1708 Status
= gBS
->InstallProtocolInterface (
1710 &gEfiIScsiInitiatorNameProtocolGuid
,
1711 EFI_NATIVE_INTERFACE
,
1712 &gIScsiInitiatorName
1714 if (EFI_ERROR (Status
)) {
1719 // Create the private data structures.
1721 mPrivate
= AllocateZeroPool (sizeof (ISCSI_PRIVATE_DATA
));
1722 if (mPrivate
== NULL
) {
1723 Status
= EFI_OUT_OF_RESOURCES
;
1727 InitializeListHead (&mPrivate
->NicInfoList
);
1728 InitializeListHead (&mPrivate
->AttemptConfigs
);
1731 // Initialize the configuration form of iSCSI.
1733 Status
= IScsiConfigFormInit (gIScsiIp4DriverBinding
.DriverBindingHandle
);
1734 if (EFI_ERROR (Status
)) {
1739 // There should be only one EFI_AUTHENTICATION_INFO_PROTOCOL. If already exists,
1740 // do not produce the protocol instance.
1742 Status
= gBS
->LocateProtocol (
1743 &gEfiAuthenticationInfoProtocolGuid
,
1745 (VOID
**) &AuthenticationInfo
1747 if (Status
== EFI_NOT_FOUND
) {
1748 Status
= gBS
->InstallProtocolInterface (
1750 &gEfiAuthenticationInfoProtocolGuid
,
1751 EFI_NATIVE_INTERFACE
,
1752 &gIScsiAuthenticationInfo
1754 if (EFI_ERROR (Status
)) {
1762 IScsiConfigFormUnload (gIScsiIp4DriverBinding
.DriverBindingHandle
);
1765 FreePool (mPrivate
);
1768 gBS
->UninstallMultipleProtocolInterfaces (
1770 &gEfiIScsiInitiatorNameProtocolGuid
,
1771 &gIScsiInitiatorName
,
1776 gBS
->UninstallMultipleProtocolInterfaces (
1777 gIScsiIp6DriverBinding
.DriverBindingHandle
,
1778 &gEfiDriverBindingProtocolGuid
,
1779 &gIScsiIp6DriverBinding
,
1780 &gEfiComponentName2ProtocolGuid
,
1781 &gIScsiComponentName2
,
1782 &gEfiComponentNameProtocolGuid
,
1783 &gIScsiComponentName
,
1788 gBS
->UninstallMultipleProtocolInterfaces (
1790 &gEfiDriverBindingProtocolGuid
,
1791 &gIScsiIp4DriverBinding
,
1792 &gEfiComponentName2ProtocolGuid
,
1793 &gIScsiComponentName2
,
1794 &gEfiComponentNameProtocolGuid
,
1795 &gIScsiComponentName
,