2 The entry point of IScsi driver.
4 Copyright (c) 2019, NVIDIA Corporation. All rights reserved.
5 Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
6 (C) Copyright 2017 Hewlett Packard Enterprise Development LP<BR>
8 SPDX-License-Identifier: BSD-2-Clause-Patent
12 #include "IScsiImpl.h"
14 EFI_DRIVER_BINDING_PROTOCOL gIScsiIp4DriverBinding
= {
15 IScsiIp4DriverBindingSupported
,
16 IScsiIp4DriverBindingStart
,
17 IScsiIp4DriverBindingStop
,
23 EFI_DRIVER_BINDING_PROTOCOL gIScsiIp6DriverBinding
= {
24 IScsiIp6DriverBindingSupported
,
25 IScsiIp6DriverBindingStart
,
26 IScsiIp6DriverBindingStop
,
32 EFI_GUID gIScsiV4PrivateGuid
= ISCSI_V4_PRIVATE_GUID
;
33 EFI_GUID gIScsiV6PrivateGuid
= ISCSI_V6_PRIVATE_GUID
;
34 ISCSI_PRIVATE_DATA
*mPrivate
= NULL
;
37 Tests to see if this driver supports the RemainingDevicePath.
39 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
40 parameter is ignored by device drivers, and is optional for bus
41 drivers. For bus drivers, if this parameter is not NULL, then
42 the bus driver must determine if the bus controller specified
43 by ControllerHandle and the child controller specified
44 by RemainingDevicePath are both supported by this
47 @retval EFI_SUCCESS The RemainingDevicePath is supported or NULL.
48 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
49 RemainingDevicePath is not supported by the driver specified by This.
52 IScsiIsDevicePathSupported (
53 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
56 EFI_DEVICE_PATH_PROTOCOL
*CurrentDevicePath
;
58 CurrentDevicePath
= RemainingDevicePath
;
59 if (CurrentDevicePath
!= NULL
) {
60 while (!IsDevicePathEnd (CurrentDevicePath
)) {
61 if ((CurrentDevicePath
->Type
== MESSAGING_DEVICE_PATH
) && (CurrentDevicePath
->SubType
== MSG_ISCSI_DP
)) {
65 CurrentDevicePath
= NextDevicePathNode (CurrentDevicePath
);
68 return EFI_UNSUPPORTED
;
75 Check whether an iSCSI HBA adapter already installs an AIP instance with
76 network boot policy matching the value specified in PcdIScsiAIPNetworkBootPolicy.
77 If yes, return EFI_SUCCESS.
79 @retval EFI_SUCCESS Found an AIP with matching network boot policy.
80 @retval EFI_NOT_FOUND AIP is unavailable or the network boot policy
89 EFI_HANDLE
*AipHandleBuffer
;
91 EFI_ADAPTER_INFORMATION_PROTOCOL
*Aip
;
92 EFI_EXT_SCSI_PASS_THRU_PROTOCOL
*ExtScsiPassThru
;
93 EFI_GUID
*InfoTypesBuffer
;
94 UINTN InfoTypeBufferCount
;
99 EFI_ADAPTER_INFO_NETWORK_BOOT
*NetworkBoot
;
101 UINT8 NetworkBootPolicy
;
104 // Check any AIP instances exist in system.
107 AipHandleBuffer
= NULL
;
108 Status
= gBS
->LocateHandleBuffer (
110 &gEfiAdapterInformationProtocolGuid
,
115 if (EFI_ERROR (Status
) || AipHandleCount
== 0) {
116 return EFI_NOT_FOUND
;
119 ASSERT (AipHandleBuffer
!= NULL
);
123 for (AipIndex
= 0; AipIndex
< AipHandleCount
; AipIndex
++) {
124 Status
= gBS
->HandleProtocol (
125 AipHandleBuffer
[AipIndex
],
126 &gEfiAdapterInformationProtocolGuid
,
129 ASSERT_EFI_ERROR (Status
);
130 ASSERT (Aip
!= NULL
);
132 Status
= gBS
->HandleProtocol (
133 AipHandleBuffer
[AipIndex
],
134 &gEfiExtScsiPassThruProtocolGuid
,
135 (VOID
*) &ExtScsiPassThru
137 if (EFI_ERROR (Status
) || ExtScsiPassThru
== NULL
) {
141 InfoTypesBuffer
= NULL
;
142 InfoTypeBufferCount
= 0;
143 Status
= Aip
->GetSupportedTypes (Aip
, &InfoTypesBuffer
, &InfoTypeBufferCount
);
144 if (EFI_ERROR (Status
) || InfoTypesBuffer
== NULL
) {
148 // Check whether the AIP instance has Network boot information block.
151 for (TypeIndex
= 0; TypeIndex
< InfoTypeBufferCount
; TypeIndex
++) {
152 if (CompareGuid (&InfoTypesBuffer
[TypeIndex
], &gEfiAdapterInfoNetworkBootGuid
)) {
158 FreePool (InfoTypesBuffer
);
164 // We now have network boot information block.
168 Status
= Aip
->GetInformation (Aip
, &gEfiAdapterInfoNetworkBootGuid
, &InfoBlock
, &InfoBlockSize
);
169 if (EFI_ERROR (Status
) || InfoBlock
== NULL
) {
174 // Check whether the network boot policy matches.
176 NetworkBoot
= (EFI_ADAPTER_INFO_NETWORK_BOOT
*) InfoBlock
;
177 NetworkBootPolicy
= PcdGet8 (PcdIScsiAIPNetworkBootPolicy
);
179 if (NetworkBootPolicy
== STOP_UEFI_ISCSI_IF_HBA_INSTALL_AIP
) {
180 Status
= EFI_SUCCESS
;
183 if (((NetworkBootPolicy
& STOP_UEFI_ISCSI_IF_AIP_SUPPORT_IP4
) != 0 &&
184 !NetworkBoot
->iScsiIpv4BootCapablity
) ||
185 ((NetworkBootPolicy
& STOP_UEFI_ISCSI_IF_AIP_SUPPORT_IP6
) != 0 &&
186 !NetworkBoot
->iScsiIpv6BootCapablity
) ||
187 ((NetworkBootPolicy
& STOP_UEFI_ISCSI_IF_AIP_SUPPORT_OFFLOAD
) != 0 &&
188 !NetworkBoot
->OffloadCapability
) ||
189 ((NetworkBootPolicy
& STOP_UEFI_ISCSI_IF_AIP_SUPPORT_MPIO
) != 0 &&
190 !NetworkBoot
->iScsiMpioCapability
) ||
191 ((NetworkBootPolicy
& STOP_UEFI_ISCSI_IF_AIP_CONFIGURED_IP4
) != 0 &&
192 !NetworkBoot
->iScsiIpv4Boot
) ||
193 ((NetworkBootPolicy
& STOP_UEFI_ISCSI_IF_AIP_CONFIGURED_IP6
) != 0 &&
194 !NetworkBoot
->iScsiIpv6Boot
)) {
195 FreePool (InfoBlock
);
199 Status
= EFI_SUCCESS
;
203 Status
= EFI_NOT_FOUND
;
206 if (InfoBlock
!= NULL
) {
207 FreePool (InfoBlock
);
209 if (AipHandleBuffer
!= NULL
) {
210 FreePool (AipHandleBuffer
);
216 Tests to see if this driver supports a given controller. This is the worker function for
217 IScsiIp4(6)DriverBindingSupported.
219 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
220 @param[in] ControllerHandle The handle of the controller to test. This handle
221 must support a protocol interface that supplies
222 an I/O abstraction to the driver.
223 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
224 parameter is ignored by device drivers, and is optional for bus
225 drivers. For bus drivers, if this parameter is not NULL, then
226 the bus driver must determine if the bus controller specified
227 by ControllerHandle and the child controller specified
228 by RemainingDevicePath are both supported by this
230 @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6.
232 @retval EFI_SUCCESS The device specified by ControllerHandle and
233 RemainingDevicePath is supported by the driver specified by This.
234 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
235 RemainingDevicePath is already being managed by the driver
237 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
238 RemainingDevicePath is not supported by the driver specified by This.
243 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
244 IN EFI_HANDLE ControllerHandle
,
245 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
,
250 EFI_GUID
*IScsiServiceBindingGuid
;
251 EFI_GUID
*TcpServiceBindingGuid
;
252 EFI_GUID
*DhcpServiceBindingGuid
;
253 EFI_GUID
*DnsServiceBindingGuid
;
255 if (IpVersion
== IP_VERSION_4
) {
256 IScsiServiceBindingGuid
= &gIScsiV4PrivateGuid
;
257 TcpServiceBindingGuid
= &gEfiTcp4ServiceBindingProtocolGuid
;
258 DhcpServiceBindingGuid
= &gEfiDhcp4ServiceBindingProtocolGuid
;
259 DnsServiceBindingGuid
= &gEfiDns4ServiceBindingProtocolGuid
;
262 IScsiServiceBindingGuid
= &gIScsiV6PrivateGuid
;
263 TcpServiceBindingGuid
= &gEfiTcp6ServiceBindingProtocolGuid
;
264 DhcpServiceBindingGuid
= &gEfiDhcp6ServiceBindingProtocolGuid
;
265 DnsServiceBindingGuid
= &gEfiDns6ServiceBindingProtocolGuid
;
268 Status
= gBS
->OpenProtocol (
270 IScsiServiceBindingGuid
,
272 This
->DriverBindingHandle
,
274 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
276 if (!EFI_ERROR (Status
)) {
277 return EFI_ALREADY_STARTED
;
280 Status
= gBS
->OpenProtocol (
282 TcpServiceBindingGuid
,
284 This
->DriverBindingHandle
,
286 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
288 if (EFI_ERROR (Status
)) {
289 return EFI_UNSUPPORTED
;
292 Status
= IScsiIsDevicePathSupported (RemainingDevicePath
);
293 if (EFI_ERROR (Status
)) {
294 return EFI_UNSUPPORTED
;
297 if (IScsiDhcpIsConfigured (ControllerHandle
, IpVersion
)) {
298 Status
= gBS
->OpenProtocol (
300 DhcpServiceBindingGuid
,
302 This
->DriverBindingHandle
,
304 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
306 if (EFI_ERROR (Status
)) {
307 return EFI_UNSUPPORTED
;
311 if (IScsiDnsIsConfigured (ControllerHandle
)) {
312 Status
= gBS
->OpenProtocol (
314 DnsServiceBindingGuid
,
316 This
->DriverBindingHandle
,
318 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
320 if (EFI_ERROR (Status
)) {
321 return EFI_UNSUPPORTED
;
330 Start to manage the controller. This is the worker function for
331 IScsiIp4(6)DriverBindingStart.
333 @param[in] Image Handle of the image.
334 @param[in] ControllerHandle Handle of the controller.
335 @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6.
337 @retval EFI_SUCCESS This driver was started.
338 @retval EFI_ALREADY_STARTED This driver is already running on this device.
339 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
340 @retval EFI_NOT_FOUND There is no sufficient information to establish
342 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
343 @retval EFI_DEVICE_ERROR Failed to get TCP connection device path.
344 @retval EFI_ACCESS_DENIED The protocol could not be removed from the Handle
345 because its interfaces are being used.
351 IN EFI_HANDLE ControllerHandle
,
356 ISCSI_DRIVER_DATA
*Private
;
358 LIST_ENTRY
*NextEntry
;
359 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
360 ISCSI_SESSION
*Session
;
362 EFI_EXT_SCSI_PASS_THRU_PROTOCOL
*ExistIScsiExtScsiPassThru
;
363 ISCSI_DRIVER_DATA
*ExistPrivate
;
364 UINT8
*AttemptConfigOrder
;
365 UINTN AttemptConfigOrderSize
;
367 EFI_HANDLE
*HandleBuffer
;
368 UINTN NumberOfHandles
;
369 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
370 EFI_GUID
*IScsiPrivateGuid
;
371 EFI_GUID
*TcpServiceBindingGuid
;
374 EFI_GUID
*ProtocolGuid
;
375 UINT8 NetworkBootPolicy
;
376 ISCSI_SESSION_CONFIG_NVDATA
*NvData
;
379 // Test to see if iSCSI driver supports the given controller.
382 if (IpVersion
== IP_VERSION_4
) {
383 IScsiPrivateGuid
= &gIScsiV4PrivateGuid
;
384 TcpServiceBindingGuid
= &gEfiTcp4ServiceBindingProtocolGuid
;
385 ProtocolGuid
= &gEfiTcp4ProtocolGuid
;
386 } else if (IpVersion
== IP_VERSION_6
) {
387 IScsiPrivateGuid
= &gIScsiV6PrivateGuid
;
388 TcpServiceBindingGuid
= &gEfiTcp6ServiceBindingProtocolGuid
;
389 ProtocolGuid
= &gEfiTcp6ProtocolGuid
;
391 return EFI_INVALID_PARAMETER
;
394 Status
= gBS
->OpenProtocol (
400 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
402 if (!EFI_ERROR (Status
)) {
403 return EFI_ALREADY_STARTED
;
406 Status
= gBS
->OpenProtocol (
408 TcpServiceBindingGuid
,
412 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
414 if (EFI_ERROR (Status
)) {
415 return EFI_UNSUPPORTED
;
418 NetworkBootPolicy
= PcdGet8 (PcdIScsiAIPNetworkBootPolicy
);
419 if (NetworkBootPolicy
== ALWAYS_USE_ISCSI_HBA_AND_IGNORE_UEFI_ISCSI
) {
423 if (NetworkBootPolicy
!= ALWAYS_USE_UEFI_ISCSI_AND_IGNORE_ISCSI_HBA
) {
425 // Check existing iSCSI AIP.
427 Status
= IScsiCheckAip ();
428 if (!EFI_ERROR (Status
)) {
430 // Find iSCSI AIP with specified network boot policy. return EFI_ABORTED.
437 // Record the incoming NIC info.
439 Status
= IScsiAddNic (ControllerHandle
, Image
);
440 if (EFI_ERROR (Status
)) {
445 // Create the instance private data.
447 Private
= IScsiCreateDriverData (Image
, ControllerHandle
);
448 if (Private
== NULL
) {
449 return EFI_OUT_OF_RESOURCES
;
453 // Create a underlayer child instance, but not need to configure it. Just open ChildHandle
454 // via BY_DRIVER. That is, establishing the relationship between ControllerHandle and ChildHandle.
455 // Therefore, when DisconnectController(), especially VLAN virtual controller handle,
456 // IScsiDriverBindingStop() will be called.
458 Status
= NetLibCreateServiceChild (
461 TcpServiceBindingGuid
,
462 &Private
->ChildHandle
465 if (EFI_ERROR (Status
)) {
469 Status
= gBS
->OpenProtocol (
470 Private
->ChildHandle
, /// Default Tcp child
475 EFI_OPEN_PROTOCOL_BY_DRIVER
478 if (EFI_ERROR (Status
)) {
483 // Always install private protocol no matter what happens later. We need to
484 // keep the relationship between ControllerHandle and ChildHandle.
486 Status
= gBS
->InstallProtocolInterface (
489 EFI_NATIVE_INTERFACE
,
490 &Private
->IScsiIdentifier
492 if (EFI_ERROR (Status
)) {
496 if (IpVersion
== IP_VERSION_4
) {
497 mPrivate
->Ipv6Flag
= FALSE
;
499 mPrivate
->Ipv6Flag
= TRUE
;
503 // Get the current iSCSI configuration data.
505 Status
= IScsiGetConfigData (Private
);
506 if (EFI_ERROR (Status
)) {
511 // If there is already a successul attempt, check whether this attempt is the
512 // first "enabled for MPIO" attempt. If not, still try the first attempt.
513 // In single path mode, try all attempts.
516 Status
= EFI_NOT_FOUND
;
518 if (mPrivate
->OneSessionEstablished
&& mPrivate
->EnableMpio
) {
519 AttemptConfigData
= NULL
;
520 NET_LIST_FOR_EACH (Entry
, &mPrivate
->AttemptConfigs
) {
521 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
522 if (AttemptConfigData
->SessionConfigData
.Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
527 if (AttemptConfigData
== NULL
) {
531 if (AttemptConfigData
->AttemptConfigIndex
== mPrivate
->BootSelectedIndex
) {
536 // Uninstall the original ExtScsiPassThru first.
540 // Locate all ExtScsiPassThru protocol instances.
542 Status
= gBS
->LocateHandleBuffer (
544 &gEfiExtScsiPassThruProtocolGuid
,
549 if (EFI_ERROR (Status
)) {
554 // Find ExtScsiPassThru protocol instance produced by this driver.
556 ExistIScsiExtScsiPassThru
= NULL
;
557 for (Index
= 0; Index
< NumberOfHandles
&& ExistIScsiExtScsiPassThru
== NULL
; Index
++) {
558 Status
= gBS
->HandleProtocol (
560 &gEfiDevicePathProtocolGuid
,
561 (VOID
**) &DevicePath
563 if (EFI_ERROR (Status
)) {
567 while (!IsDevicePathEnd (DevicePath
)) {
568 if ((DevicePath
->Type
== MESSAGING_DEVICE_PATH
) && (DevicePath
->SubType
== MSG_MAC_ADDR_DP
)) {
570 // Get the ExtScsiPassThru protocol instance.
572 Status
= gBS
->HandleProtocol (
574 &gEfiExtScsiPassThruProtocolGuid
,
575 (VOID
**) &ExistIScsiExtScsiPassThru
577 ASSERT_EFI_ERROR (Status
);
581 DevicePath
= NextDevicePathNode (DevicePath
);
585 FreePool (HandleBuffer
);
587 if (ExistIScsiExtScsiPassThru
== NULL
) {
588 Status
= EFI_NOT_FOUND
;
592 ExistPrivate
= ISCSI_DRIVER_DATA_FROM_EXT_SCSI_PASS_THRU (ExistIScsiExtScsiPassThru
);
594 Status
= gBS
->UninstallProtocolInterface (
595 ExistPrivate
->ExtScsiPassThruHandle
,
596 &gEfiExtScsiPassThruProtocolGuid
,
597 &ExistPrivate
->IScsiExtScsiPassThru
599 if (EFI_ERROR (Status
)) {
605 // Install the Ext SCSI PASS THRU protocol.
607 Status
= gBS
->InstallProtocolInterface (
608 &Private
->ExtScsiPassThruHandle
,
609 &gEfiExtScsiPassThruProtocolGuid
,
610 EFI_NATIVE_INTERFACE
,
611 &Private
->IScsiExtScsiPassThru
613 if (EFI_ERROR (Status
)) {
619 NET_LIST_FOR_EACH_SAFE (Entry
, NextEntry
, &mPrivate
->AttemptConfigs
) {
620 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
622 // Don't process the attempt that does not associate with the current NIC or
623 // this attempt is disabled or established.
625 if (AttemptConfigData
->NicIndex
!= mPrivate
->CurrentNic
||
626 AttemptConfigData
->SessionConfigData
.Enabled
== ISCSI_DISABLED
||
627 AttemptConfigData
->ValidPath
) {
632 // In multipath mode, don't process attempts configured for single path.
633 // In default single path mode, don't process attempts configured for multipath.
635 if ((mPrivate
->EnableMpio
&&
636 AttemptConfigData
->SessionConfigData
.Enabled
!= ISCSI_ENABLED_FOR_MPIO
) ||
637 (!mPrivate
->EnableMpio
&&
638 AttemptConfigData
->SessionConfigData
.Enabled
!= ISCSI_ENABLED
)) {
643 // Don't process the attempt that fails to get the init/target information from DHCP.
645 if (AttemptConfigData
->SessionConfigData
.InitiatorInfoFromDhcp
&&
646 !AttemptConfigData
->DhcpSuccess
) {
647 if (!mPrivate
->EnableMpio
&& mPrivate
->ValidSinglePathCount
> 0) {
648 mPrivate
->ValidSinglePathCount
--;
654 // Don't process the autoconfigure path if it is already established.
656 if (AttemptConfigData
->SessionConfigData
.IpMode
== IP_MODE_AUTOCONFIG
&&
657 AttemptConfigData
->AutoConfigureSuccess
) {
662 // Don't process the attempt if its IP mode is not in the current IP version.
664 if (!mPrivate
->Ipv6Flag
) {
665 if (AttemptConfigData
->SessionConfigData
.IpMode
== IP_MODE_IP6
) {
668 if (AttemptConfigData
->SessionConfigData
.IpMode
== IP_MODE_AUTOCONFIG
&&
669 AttemptConfigData
->AutoConfigureMode
== IP_MODE_AUTOCONFIG_IP6
) {
673 if (AttemptConfigData
->SessionConfigData
.IpMode
== IP_MODE_IP4
) {
676 if (AttemptConfigData
->SessionConfigData
.IpMode
== IP_MODE_AUTOCONFIG
&&
677 AttemptConfigData
->AutoConfigureMode
== IP_MODE_AUTOCONFIG_IP4
) {
683 // Fill in the Session and init it.
685 Session
= (ISCSI_SESSION
*) AllocateZeroPool (sizeof (ISCSI_SESSION
));
686 if (Session
== NULL
) {
687 Status
= EFI_OUT_OF_RESOURCES
;
691 Session
->Private
= Private
;
692 Session
->ConfigData
= AttemptConfigData
;
693 Session
->AuthType
= AttemptConfigData
->AuthenticationType
;
696 mPrivate
->PortString
,
697 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
699 (UINTN
) AttemptConfigData
->AttemptConfigIndex
702 if (Session
->AuthType
== ISCSI_AUTH_TYPE_CHAP
) {
703 Session
->AuthData
.CHAP
.AuthConfig
= &AttemptConfigData
->AuthConfigData
.CHAP
;
706 IScsiSessionInit (Session
, FALSE
);
709 // Try to login and create an iSCSI session according to the configuration.
711 Status
= IScsiSessionLogin (Session
);
712 if (Status
== EFI_MEDIA_CHANGED
) {
714 // The specified target is not available, and the redirection information is
715 // received. Login the session again with the updated target address.
717 Status
= IScsiSessionLogin (Session
);
718 } else if (Status
== EFI_NOT_READY
) {
719 Status
= IScsiSessionReLogin (Session
);
723 // Restore the original user setting which specifies the proxy/virtual iSCSI target to NV region.
725 NvData
= &AttemptConfigData
->SessionConfigData
;
726 if (NvData
->RedirectFlag
) {
727 NvData
->TargetPort
= NvData
->OriginalTargetPort
;
728 CopyMem (&NvData
->TargetIp
, &NvData
->OriginalTargetIp
, sizeof (EFI_IP_ADDRESS
));
729 NvData
->RedirectFlag
= FALSE
;
732 mPrivate
->PortString
,
733 &gEfiIScsiInitiatorNameProtocolGuid
,
734 ISCSI_CONFIG_VAR_ATTR
,
735 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA
),
740 if (EFI_ERROR (Status
)) {
742 // In Single path mode, only the successful attempt will be recorded in iBFT;
743 // in multi-path mode, all the attempt entries in MPIO will be recorded in iBFT.
745 if (!mPrivate
->EnableMpio
&& mPrivate
->ValidSinglePathCount
> 0) {
746 mPrivate
->ValidSinglePathCount
--;
752 AttemptConfigData
->ValidPath
= TRUE
;
755 // Do not record the attempt in iBFT if it login with KRB5.
756 // TODO: record KRB5 attempt information in the iSCSI device path.
758 if (Session
->AuthType
== ISCSI_AUTH_TYPE_KRB
) {
759 if (!mPrivate
->EnableMpio
&& mPrivate
->ValidSinglePathCount
> 0) {
760 mPrivate
->ValidSinglePathCount
--;
763 AttemptConfigData
->ValidiBFTPath
= FALSE
;
765 AttemptConfigData
->ValidiBFTPath
= TRUE
;
769 // IScsi session success. Update the attempt state to NVR.
771 if (AttemptConfigData
->SessionConfigData
.IpMode
== IP_MODE_AUTOCONFIG
) {
772 AttemptConfigData
->AutoConfigureSuccess
= TRUE
;
776 mPrivate
->PortString
,
777 &gEfiIScsiInitiatorNameProtocolGuid
,
778 ISCSI_CONFIG_VAR_ATTR
,
779 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA
),
784 // Select the first login session. Abort others.
786 if (Private
->Session
== NULL
) {
787 Private
->Session
= Session
;
788 BootSelected
= AttemptConfigData
->AttemptConfigIndex
;
790 // Don't validate other attempt in multipath mode if one is success.
792 if (mPrivate
->EnableMpio
) {
796 IScsiSessionAbort (Session
);
803 // All attempts configured for this driver instance are not valid.
805 if (Private
->Session
== NULL
) {
806 Status
= gBS
->UninstallProtocolInterface (
807 Private
->ExtScsiPassThruHandle
,
808 &gEfiExtScsiPassThruProtocolGuid
,
809 &Private
->IScsiExtScsiPassThru
811 ASSERT_EFI_ERROR (Status
);
812 Private
->ExtScsiPassThruHandle
= NULL
;
815 // Reinstall the original ExtScsiPassThru back.
817 if (mPrivate
->OneSessionEstablished
&& ExistPrivate
!= NULL
) {
818 Status
= gBS
->InstallProtocolInterface (
819 &ExistPrivate
->ExtScsiPassThruHandle
,
820 &gEfiExtScsiPassThruProtocolGuid
,
821 EFI_NATIVE_INTERFACE
,
822 &ExistPrivate
->IScsiExtScsiPassThru
824 if (EFI_ERROR (Status
)) {
831 Status
= EFI_NOT_FOUND
;
838 // More than one attempt successes.
840 if (Private
->Session
!= NULL
&& mPrivate
->OneSessionEstablished
) {
842 AttemptConfigOrder
= IScsiGetVariableAndSize (
845 &AttemptConfigOrderSize
847 if (AttemptConfigOrder
== NULL
) {
850 for (Index
= 0; Index
< AttemptConfigOrderSize
/ sizeof (UINT8
); Index
++) {
851 if (AttemptConfigOrder
[Index
] == mPrivate
->BootSelectedIndex
||
852 AttemptConfigOrder
[Index
] == BootSelected
) {
857 if (mPrivate
->EnableMpio
) {
859 // Use the attempt in earlier order. Abort the later one in MPIO.
861 if (AttemptConfigOrder
[Index
] == mPrivate
->BootSelectedIndex
) {
862 IScsiSessionAbort (Private
->Session
);
863 FreePool (Private
->Session
);
864 Private
->Session
= NULL
;
865 gBS
->UninstallProtocolInterface (
866 Private
->ExtScsiPassThruHandle
,
867 &gEfiExtScsiPassThruProtocolGuid
,
868 &Private
->IScsiExtScsiPassThru
870 Private
->ExtScsiPassThruHandle
= NULL
;
873 // Reinstall the original ExtScsiPassThru back.
875 Status
= gBS
->InstallProtocolInterface (
876 &ExistPrivate
->ExtScsiPassThruHandle
,
877 &gEfiExtScsiPassThruProtocolGuid
,
878 EFI_NATIVE_INTERFACE
,
879 &ExistPrivate
->IScsiExtScsiPassThru
881 if (EFI_ERROR (Status
)) {
887 if (AttemptConfigOrder
[Index
] != BootSelected
) {
890 mPrivate
->BootSelectedIndex
= BootSelected
;
892 // Clear the resource in ExistPrivate.
894 gBS
->UninstallProtocolInterface (
895 ExistPrivate
->Controller
,
897 &ExistPrivate
->IScsiIdentifier
900 IScsiRemoveNic (ExistPrivate
->Controller
);
901 if (ExistPrivate
->Session
!= NULL
) {
902 IScsiSessionAbort (ExistPrivate
->Session
);
905 if (ExistPrivate
->DevicePath
!= NULL
) {
906 Status
= gBS
->UninstallProtocolInterface (
907 ExistPrivate
->ExtScsiPassThruHandle
,
908 &gEfiDevicePathProtocolGuid
,
909 ExistPrivate
->DevicePath
911 if (EFI_ERROR (Status
)) {
915 FreePool (ExistPrivate
->DevicePath
);
918 gBS
->CloseEvent (ExistPrivate
->ExitBootServiceEvent
);
919 FreePool (ExistPrivate
);
924 // Use the attempt in earlier order as boot selected in single path mode.
926 if (AttemptConfigOrder
[Index
] == mPrivate
->BootSelectedIndex
) {
934 mPrivate
->OneSessionEstablished
= TRUE
;
935 mPrivate
->BootSelectedIndex
= BootSelected
;
939 // Duplicate the Session's tcp connection device path. The source port field
940 // will be set to zero as one iSCSI session is comprised of several iSCSI
943 Private
->DevicePath
= IScsiGetTcpConnDevicePath (Private
->Session
);
944 if (Private
->DevicePath
== NULL
) {
945 Status
= EFI_DEVICE_ERROR
;
949 // Install the updated device path onto the ExtScsiPassThruHandle.
951 Status
= gBS
->InstallProtocolInterface (
952 &Private
->ExtScsiPassThruHandle
,
953 &gEfiDevicePathProtocolGuid
,
954 EFI_NATIVE_INTERFACE
,
957 if (EFI_ERROR (Status
)) {
962 // ISCSI children should share the default Tcp child, just open the default Tcp child via BY_CHILD_CONTROLLER.
964 Status
= gBS
->OpenProtocol (
965 Private
->ChildHandle
, /// Default Tcp child
969 Private
->ExtScsiPassThruHandle
,
970 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
972 if (EFI_ERROR (Status
)) {
973 gBS
->UninstallMultipleProtocolInterfaces (
974 Private
->ExtScsiPassThruHandle
,
975 &gEfiExtScsiPassThruProtocolGuid
,
976 &Private
->IScsiExtScsiPassThru
,
977 &gEfiDevicePathProtocolGuid
,
988 // Update/Publish the iSCSI Boot Firmware Table.
990 if (mPrivate
->BootSelectedIndex
!= 0) {
998 if (Private
->Session
!= NULL
) {
999 IScsiSessionAbort (Private
->Session
);
1006 Stops a device controller or a bus controller. This is the worker function for
1007 IScsiIp4(6)DriverBindingStop.
1009 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
1010 @param[in] ControllerHandle A handle to the device being stopped. The handle must
1011 support a bus specific I/O protocol for the driver
1012 to use to stop the device.
1013 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
1014 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
1015 if NumberOfChildren is 0.
1016 @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6.
1018 @retval EFI_SUCCESS The device was stopped.
1019 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
1020 @retval EFI_INVALID_PARAMETER Child handle is NULL.
1021 @retval EFI_ACCESS_DENIED The protocol could not be removed from the Handle
1022 because its interfaces are being used.
1028 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1029 IN EFI_HANDLE ControllerHandle
,
1030 IN UINTN NumberOfChildren
,
1031 IN EFI_HANDLE
*ChildHandleBuffer OPTIONAL
,
1035 EFI_HANDLE IScsiController
;
1037 ISCSI_PRIVATE_PROTOCOL
*IScsiIdentifier
;
1038 ISCSI_DRIVER_DATA
*Private
;
1039 EFI_EXT_SCSI_PASS_THRU_PROTOCOL
*PassThru
;
1040 ISCSI_CONNECTION
*Conn
;
1041 EFI_GUID
*ProtocolGuid
;
1042 EFI_GUID
*TcpServiceBindingGuid
;
1043 EFI_GUID
*TcpProtocolGuid
;
1046 if (NumberOfChildren
!= 0) {
1048 // We should have only one child.
1050 Status
= gBS
->OpenProtocol (
1051 ChildHandleBuffer
[0],
1052 &gEfiExtScsiPassThruProtocolGuid
,
1053 (VOID
**) &PassThru
,
1054 This
->DriverBindingHandle
,
1056 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1058 if (EFI_ERROR (Status
)) {
1059 return EFI_DEVICE_ERROR
;
1062 Private
= ISCSI_DRIVER_DATA_FROM_EXT_SCSI_PASS_THRU (PassThru
);
1063 Conn
= NET_LIST_HEAD (&Private
->Session
->Conns
, ISCSI_CONNECTION
, Link
);
1066 // Previously the TCP protocol is opened BY_CHILD_CONTROLLER. Just close
1067 // the protocol here, but do not uninstall the device path protocol and
1068 // EXT SCSI PASS THRU protocol installed on ExtScsiPassThruHandle.
1070 if (IpVersion
== IP_VERSION_4
) {
1071 ProtocolGuid
= &gEfiTcp4ProtocolGuid
;
1073 ProtocolGuid
= &gEfiTcp6ProtocolGuid
;
1076 gBS
->CloseProtocol (
1077 Private
->ChildHandle
,
1080 Private
->ExtScsiPassThruHandle
1083 gBS
->CloseProtocol (
1087 Private
->ExtScsiPassThruHandle
1094 // Get the handle of the controller we are controlling.
1096 if (IpVersion
== IP_VERSION_4
) {
1097 ProtocolGuid
= &gIScsiV4PrivateGuid
;
1098 TcpProtocolGuid
= &gEfiTcp4ProtocolGuid
;
1099 TcpServiceBindingGuid
= &gEfiTcp4ServiceBindingProtocolGuid
;
1101 ProtocolGuid
= &gIScsiV6PrivateGuid
;
1102 TcpProtocolGuid
= &gEfiTcp6ProtocolGuid
;
1103 TcpServiceBindingGuid
= &gEfiTcp6ServiceBindingProtocolGuid
;
1105 IScsiController
= NetLibGetNicHandle (ControllerHandle
, TcpProtocolGuid
);
1106 if (IScsiController
== NULL
) {
1110 Status
= gBS
->OpenProtocol (
1113 (VOID
**) &IScsiIdentifier
,
1114 This
->DriverBindingHandle
,
1116 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1118 if (EFI_ERROR (Status
)) {
1119 return EFI_DEVICE_ERROR
;
1122 Private
= ISCSI_DRIVER_DATA_FROM_IDENTIFIER (IScsiIdentifier
);
1123 ASSERT (Private
!= NULL
);
1125 if (Private
->ChildHandle
!= NULL
) {
1126 Status
= gBS
->CloseProtocol (
1127 Private
->ChildHandle
,
1129 This
->DriverBindingHandle
,
1133 ASSERT (!EFI_ERROR (Status
));
1135 Status
= NetLibDestroyServiceChild (
1137 This
->DriverBindingHandle
,
1138 TcpServiceBindingGuid
,
1139 Private
->ChildHandle
1142 ASSERT (!EFI_ERROR (Status
));
1145 gBS
->UninstallProtocolInterface (
1148 &Private
->IScsiIdentifier
1154 IScsiRemoveNic (IScsiController
);
1157 // Update the iSCSI Boot Firmware Table.
1159 IScsiPublishIbft ();
1161 if (Private
->Session
!= NULL
) {
1162 IScsiSessionAbort (Private
->Session
);
1165 Status
= IScsiCleanDriverData (Private
);
1167 if (EFI_ERROR (Status
)) {
1175 Tests to see if this driver supports a given controller. If a child device is provided,
1176 it tests to see if this driver supports creating a handle for the specified child device.
1178 This function checks to see if the driver specified by This supports the device specified by
1179 ControllerHandle. Drivers typically use the device path attached to
1180 ControllerHandle and/or the services from the bus I/O abstraction attached to
1181 ControllerHandle to determine if the driver supports ControllerHandle. This function
1182 may be called many times during platform initialization. In order to reduce boot times, the tests
1183 performed by this function must be very small and take as little time as possible to execute. This
1184 function must not change the state of any hardware devices, and this function must be aware that the
1185 device specified by ControllerHandle may already be managed by the same driver or a
1186 different driver. This function must match its calls to AllocatePages() with FreePages(),
1187 AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
1188 Since ControllerHandle may have been previously started by the same driver, if a protocol is
1189 already in the opened state, then it must not be closed with CloseProtocol(). This is required
1190 to guarantee the state of ControllerHandle is not modified by this function.
1192 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
1193 @param[in] ControllerHandle The handle of the controller to test. This handle
1194 must support a protocol interface that supplies
1195 an I/O abstraction to the driver.
1196 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
1197 parameter is ignored by device drivers, and is optional for bus
1198 drivers. For bus drivers, if this parameter is not NULL, then
1199 the bus driver must determine if the bus controller specified
1200 by ControllerHandle and the child controller specified
1201 by RemainingDevicePath are both supported by this
1204 @retval EFI_SUCCESS The device specified by ControllerHandle and
1205 RemainingDevicePath is supported by the driver specified by This.
1206 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
1207 RemainingDevicePath is already managed by the driver
1209 @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
1210 RemainingDevicePath is already managed by a different
1211 driver or an application that requires exclusive access.
1212 Currently not implemented.
1213 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
1214 RemainingDevicePath is not supported by the driver specified by This.
1218 IScsiIp4DriverBindingSupported (
1219 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1220 IN EFI_HANDLE ControllerHandle
,
1221 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
1224 return IScsiSupported (
1227 RemainingDevicePath
,
1233 Starts a device controller or a bus controller.
1235 The Start() function is designed to be invoked from the EFI boot service ConnectController().
1236 As a result, much of the error checking on the parameters to Start() has been moved into this
1237 common boot service. It is legal to call Start() from other locations,
1238 but the following calling restrictions must be followed or the system behavior will not be deterministic.
1239 1. ControllerHandle must be a valid EFI_HANDLE.
1240 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
1241 EFI_DEVICE_PATH_PROTOCOL.
1242 3. Prior to calling Start(), the Supported() function for the driver specified by This must
1243 have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
1245 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
1246 @param[in] ControllerHandle The handle of the controller to start. This handle
1247 must support a protocol interface that supplies
1248 an I/O abstraction to the driver.
1249 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
1250 parameter is ignored by device drivers, and is optional for bus
1251 drivers. For a bus driver, if this parameter is NULL, then handles
1252 for all the children of Controller are created by this driver.
1253 If this parameter is not NULL and the first Device Path Node is
1254 not the End of Device Path Node, then only the handle for the
1255 child device specified by the first Device Path Node of
1256 RemainingDevicePath is created by this driver.
1257 If the first Device Path Node of RemainingDevicePath is
1258 the End of Device Path Node, no child handle is created by this
1261 @retval EFI_SUCCESS The device was started.
1262 @retval EFI_DEVICE_ERROR The device could not be started due to a device error. Currently not implemented.
1263 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
1264 @retval Others The driver failed to start the device.
1269 IScsiIp4DriverBindingStart (
1270 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1271 IN EFI_HANDLE ControllerHandle
,
1272 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
1277 Status
= IScsiStart (This
->DriverBindingHandle
, ControllerHandle
, IP_VERSION_4
);
1278 if (Status
== EFI_ALREADY_STARTED
) {
1279 Status
= EFI_SUCCESS
;
1286 Stops a device controller or a bus controller.
1288 The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
1289 As a result, much of the error checking on the parameters to Stop() has been moved
1290 into this common boot service. It is legal to call Stop() from other locations,
1291 but the following calling restrictions must be followed or the system behavior will not be deterministic.
1292 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
1293 same driver's Start() function.
1294 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
1295 EFI_HANDLE. In addition, all of these handles must have been created in this driver's
1296 Start() function, and the Start() function must have called OpenProtocol() on
1297 ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
1299 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
1300 @param[in] ControllerHandle A handle to the device being stopped. The handle must
1301 support a bus specific I/O protocol for the driver
1302 to use to stop the device.
1303 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
1304 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
1305 if NumberOfChildren is 0.
1307 @retval EFI_SUCCESS The device was stopped.
1308 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
1313 IScsiIp4DriverBindingStop (
1314 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1315 IN EFI_HANDLE ControllerHandle
,
1316 IN UINTN NumberOfChildren
,
1317 IN EFI_HANDLE
*ChildHandleBuffer OPTIONAL
1330 Tests to see if this driver supports a given controller. If a child device is provided,
1331 it tests to see if this driver supports creating a handle for the specified child device.
1333 This function checks to see if the driver specified by This supports the device specified by
1334 ControllerHandle. Drivers typically use the device path attached to
1335 ControllerHandle and/or the services from the bus I/O abstraction attached to
1336 ControllerHandle to determine if the driver supports ControllerHandle. This function
1337 may be called many times during platform initialization. In order to reduce boot times, the tests
1338 performed by this function must be very small and take as little time as possible to execute. This
1339 function must not change the state of any hardware devices, and this function must be aware that the
1340 device specified by ControllerHandle may already be managed by the same driver or a
1341 different driver. This function must match its calls to AllocatePages() with FreePages(),
1342 AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
1343 Since ControllerHandle may have been previously started by the same driver, if a protocol is
1344 already in the opened state, then it must not be closed with CloseProtocol(). This is required
1345 to guarantee the state of ControllerHandle is not modified by this function.
1347 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
1348 @param[in] ControllerHandle The handle of the controller to test. This handle
1349 must support a protocol interface that supplies
1350 an I/O abstraction to the driver.
1351 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
1352 parameter is ignored by device drivers, and is optional for bus
1353 drivers. For bus drivers, if this parameter is not NULL, then
1354 the bus driver must determine if the bus controller specified
1355 by ControllerHandle and the child controller specified
1356 by RemainingDevicePath are both supported by this
1359 @retval EFI_SUCCESS The device specified by ControllerHandle and
1360 RemainingDevicePath is supported by the driver specified by This.
1361 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
1362 RemainingDevicePath is already managed by the driver
1364 @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
1365 RemainingDevicePath is already managed by a different
1366 driver or an application that requires exclusive access.
1367 Currently not implemented.
1368 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
1369 RemainingDevicePath is not supported by the driver specified by This.
1373 IScsiIp6DriverBindingSupported (
1374 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1375 IN EFI_HANDLE ControllerHandle
,
1376 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
1379 return IScsiSupported (
1382 RemainingDevicePath
,
1388 Starts a device controller or a bus controller.
1390 The Start() function is designed to be invoked from the EFI boot service ConnectController().
1391 As a result, much of the error checking on the parameters to Start() has been moved into this
1392 common boot service. It is legal to call Start() from other locations,
1393 but the following calling restrictions must be followed or the system behavior will not be deterministic.
1394 1. ControllerHandle must be a valid EFI_HANDLE.
1395 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
1396 EFI_DEVICE_PATH_PROTOCOL.
1397 3. Prior to calling Start(), the Supported() function for the driver specified by This must
1398 have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
1400 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
1401 @param[in] ControllerHandle The handle of the controller to start. This handle
1402 must support a protocol interface that supplies
1403 an I/O abstraction to the driver.
1404 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
1405 parameter is ignored by device drivers, and is optional for bus
1406 drivers. For a bus driver, if this parameter is NULL, then handles
1407 for all the children of Controller are created by this driver.
1408 If this parameter is not NULL and the first Device Path Node is
1409 not the End of Device Path Node, then only the handle for the
1410 child device specified by the first Device Path Node of
1411 RemainingDevicePath is created by this driver.
1412 If the first Device Path Node of RemainingDevicePath is
1413 the End of Device Path Node, no child handle is created by this
1416 @retval EFI_SUCCESS The device was started.
1417 @retval EFI_DEVICE_ERROR The device could not be started due to a device error. Currently not implemented.
1418 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
1419 @retval Others The driver failed to start the device.
1424 IScsiIp6DriverBindingStart (
1425 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1426 IN EFI_HANDLE ControllerHandle
,
1427 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
1432 Status
= IScsiStart (This
->DriverBindingHandle
, ControllerHandle
, IP_VERSION_6
);
1433 if (Status
== EFI_ALREADY_STARTED
) {
1434 Status
= EFI_SUCCESS
;
1441 Stops a device controller or a bus controller.
1443 The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
1444 As a result, much of the error checking on the parameters to Stop() has been moved
1445 into this common boot service. It is legal to call Stop() from other locations,
1446 but the following calling restrictions must be followed or the system behavior will not be deterministic.
1447 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
1448 same driver's Start() function.
1449 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
1450 EFI_HANDLE. In addition, all of these handles must have been created in this driver's
1451 Start() function, and the Start() function must have called OpenProtocol() on
1452 ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
1454 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
1455 @param[in] ControllerHandle A handle to the device being stopped. The handle must
1456 support a bus specific I/O protocol for the driver
1457 to use to stop the device.
1458 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
1459 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
1460 if NumberOfChildren is 0.
1462 @retval EFI_SUCCESS The device was stopped.
1463 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
1468 IScsiIp6DriverBindingStop (
1469 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1470 IN EFI_HANDLE ControllerHandle
,
1471 IN UINTN NumberOfChildren
,
1472 IN EFI_HANDLE
*ChildHandleBuffer OPTIONAL
1485 Unload the iSCSI driver.
1487 @param[in] ImageHandle The handle of the driver image.
1489 @retval EFI_SUCCESS The driver is unloaded.
1490 @retval EFI_DEVICE_ERROR An unexpected error occurred.
1496 IN EFI_HANDLE ImageHandle
1500 UINTN DeviceHandleCount
;
1501 EFI_HANDLE
*DeviceHandleBuffer
;
1503 EFI_COMPONENT_NAME_PROTOCOL
*ComponentName
;
1504 EFI_COMPONENT_NAME2_PROTOCOL
*ComponentName2
;
1507 // Try to disconnect the driver from the devices it's controlling.
1509 Status
= gBS
->LocateHandleBuffer (
1516 if (EFI_ERROR (Status
)) {
1521 // Disconnect the iSCSI4 driver from the controlled device.
1523 for (Index
= 0; Index
< DeviceHandleCount
; Index
++) {
1524 Status
= IScsiTestManagedDevice (
1525 DeviceHandleBuffer
[Index
],
1526 gIScsiIp4DriverBinding
.DriverBindingHandle
,
1527 &gEfiTcp4ProtocolGuid
)
1529 if (EFI_ERROR (Status
)) {
1532 Status
= gBS
->DisconnectController (
1533 DeviceHandleBuffer
[Index
],
1534 gIScsiIp4DriverBinding
.DriverBindingHandle
,
1537 if (EFI_ERROR (Status
)) {
1543 // Disconnect the iSCSI6 driver from the controlled device.
1545 for (Index
= 0; Index
< DeviceHandleCount
; Index
++) {
1546 Status
= IScsiTestManagedDevice (
1547 DeviceHandleBuffer
[Index
],
1548 gIScsiIp6DriverBinding
.DriverBindingHandle
,
1549 &gEfiTcp6ProtocolGuid
1551 if (EFI_ERROR (Status
)) {
1554 Status
= gBS
->DisconnectController (
1555 DeviceHandleBuffer
[Index
],
1556 gIScsiIp6DriverBinding
.DriverBindingHandle
,
1559 if (EFI_ERROR (Status
)) {
1565 // Unload the iSCSI configuration form.
1567 Status
= IScsiConfigFormUnload (gIScsiIp4DriverBinding
.DriverBindingHandle
);
1568 if (EFI_ERROR (Status
)) {
1573 // Uninstall the protocols installed by iSCSI driver.
1575 Status
= gBS
->UninstallMultipleProtocolInterfaces (
1577 &gEfiAuthenticationInfoProtocolGuid
,
1578 &gIScsiAuthenticationInfo
,
1581 if (EFI_ERROR (Status
)) {
1585 if (gIScsiControllerNameTable
!= NULL
) {
1586 Status
= FreeUnicodeStringTable (gIScsiControllerNameTable
);
1587 if (EFI_ERROR (Status
)) {
1590 gIScsiControllerNameTable
= NULL
;
1594 // Uninstall the ComponentName and ComponentName2 protocol from iSCSI4 driver binding handle
1595 // if it has been installed.
1597 Status
= gBS
->HandleProtocol (
1598 gIScsiIp4DriverBinding
.DriverBindingHandle
,
1599 &gEfiComponentNameProtocolGuid
,
1600 (VOID
**) &ComponentName
1602 if (!EFI_ERROR (Status
)) {
1603 Status
= gBS
->UninstallMultipleProtocolInterfaces (
1604 gIScsiIp4DriverBinding
.DriverBindingHandle
,
1605 &gEfiComponentNameProtocolGuid
,
1609 if (EFI_ERROR (Status
)) {
1614 Status
= gBS
->HandleProtocol (
1615 gIScsiIp4DriverBinding
.DriverBindingHandle
,
1616 &gEfiComponentName2ProtocolGuid
,
1617 (VOID
**) &ComponentName2
1619 if (!EFI_ERROR (Status
)) {
1620 gBS
->UninstallMultipleProtocolInterfaces (
1621 gIScsiIp4DriverBinding
.DriverBindingHandle
,
1622 &gEfiComponentName2ProtocolGuid
,
1626 if (EFI_ERROR (Status
)) {
1632 // Uninstall the ComponentName and ComponentName2 protocol from iSCSI6 driver binding handle
1633 // if it has been installed.
1635 Status
= gBS
->HandleProtocol (
1636 gIScsiIp6DriverBinding
.DriverBindingHandle
,
1637 &gEfiComponentNameProtocolGuid
,
1638 (VOID
**) &ComponentName
1640 if (!EFI_ERROR (Status
)) {
1641 Status
= gBS
->UninstallMultipleProtocolInterfaces (
1642 gIScsiIp6DriverBinding
.DriverBindingHandle
,
1643 &gEfiComponentNameProtocolGuid
,
1647 if (EFI_ERROR (Status
)) {
1652 Status
= gBS
->HandleProtocol (
1653 gIScsiIp6DriverBinding
.DriverBindingHandle
,
1654 &gEfiComponentName2ProtocolGuid
,
1655 (VOID
**) &ComponentName2
1657 if (!EFI_ERROR (Status
)) {
1658 gBS
->UninstallMultipleProtocolInterfaces (
1659 gIScsiIp6DriverBinding
.DriverBindingHandle
,
1660 &gEfiComponentName2ProtocolGuid
,
1664 if (EFI_ERROR (Status
)) {
1670 // Uninstall the IScsiInitiatorNameProtocol and all the driver binding protocols.
1672 Status
= gBS
->UninstallMultipleProtocolInterfaces (
1673 gIScsiIp4DriverBinding
.DriverBindingHandle
,
1674 &gEfiDriverBindingProtocolGuid
,
1675 &gIScsiIp4DriverBinding
,
1676 &gEfiIScsiInitiatorNameProtocolGuid
,
1677 &gIScsiInitiatorName
,
1680 if (EFI_ERROR (Status
)) {
1684 Status
= gBS
->UninstallMultipleProtocolInterfaces (
1685 gIScsiIp6DriverBinding
.DriverBindingHandle
,
1686 &gEfiDriverBindingProtocolGuid
,
1687 &gIScsiIp6DriverBinding
,
1693 if (DeviceHandleBuffer
!= NULL
) {
1694 FreePool (DeviceHandleBuffer
);
1701 This is the declaration of an EFI image entry point. This entry point is
1702 the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including
1703 both device drivers and bus drivers.
1705 The entry point for iSCSI driver which initializes the global variables and
1706 installs the driver binding, component name protocol, iSCSI initiator name
1707 protocol and Authentication Info protocol on its image.
1709 @param[in] ImageHandle The firmware allocated handle for the UEFI image.
1710 @param[in] SystemTable A pointer to the EFI System Table.
1712 @retval EFI_SUCCESS The operation completed successfully.
1713 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
1718 IScsiDriverEntryPoint (
1719 IN EFI_HANDLE ImageHandle
,
1720 IN EFI_SYSTEM_TABLE
*SystemTable
1724 EFI_ISCSI_INITIATOR_NAME_PROTOCOL
*IScsiInitiatorName
;
1725 EFI_AUTHENTICATION_INFO_PROTOCOL
*AuthenticationInfo
;
1728 // There should be only one EFI_ISCSI_INITIATOR_NAME_PROTOCOL.
1730 Status
= gBS
->LocateProtocol (
1731 &gEfiIScsiInitiatorNameProtocolGuid
,
1733 (VOID
**) &IScsiInitiatorName
1735 if (!EFI_ERROR (Status
)) {
1736 return EFI_ACCESS_DENIED
;
1740 // Initialize the EFI Driver Library.
1742 Status
= EfiLibInstallDriverBindingComponentName2 (
1745 &gIScsiIp4DriverBinding
,
1747 &gIScsiComponentName
,
1748 &gIScsiComponentName2
1750 if (EFI_ERROR (Status
)) {
1754 Status
= EfiLibInstallDriverBindingComponentName2 (
1757 &gIScsiIp6DriverBinding
,
1759 &gIScsiComponentName
,
1760 &gIScsiComponentName2
1762 if (EFI_ERROR (Status
)) {
1767 // Install the iSCSI Initiator Name Protocol.
1769 Status
= gBS
->InstallProtocolInterface (
1771 &gEfiIScsiInitiatorNameProtocolGuid
,
1772 EFI_NATIVE_INTERFACE
,
1773 &gIScsiInitiatorName
1775 if (EFI_ERROR (Status
)) {
1780 // Create the private data structures.
1782 mPrivate
= AllocateZeroPool (sizeof (ISCSI_PRIVATE_DATA
));
1783 if (mPrivate
== NULL
) {
1784 Status
= EFI_OUT_OF_RESOURCES
;
1788 InitializeListHead (&mPrivate
->NicInfoList
);
1789 InitializeListHead (&mPrivate
->AttemptConfigs
);
1792 // Initialize the configuration form of iSCSI.
1794 Status
= IScsiConfigFormInit (gIScsiIp4DriverBinding
.DriverBindingHandle
);
1795 if (EFI_ERROR (Status
)) {
1800 // Create the Maximum Attempts.
1802 Status
= IScsiCreateAttempts (PcdGet8 (PcdMaxIScsiAttemptNumber
));
1803 if (EFI_ERROR (Status
)) {
1808 // Create Keywords for all the Attempts.
1810 Status
= IScsiCreateKeywords (PcdGet8 (PcdMaxIScsiAttemptNumber
));
1811 if (EFI_ERROR (Status
)) {
1816 // There should be only one EFI_AUTHENTICATION_INFO_PROTOCOL. If already exists,
1817 // do not produce the protocol instance.
1819 Status
= gBS
->LocateProtocol (
1820 &gEfiAuthenticationInfoProtocolGuid
,
1822 (VOID
**) &AuthenticationInfo
1824 if (Status
== EFI_NOT_FOUND
) {
1825 Status
= gBS
->InstallProtocolInterface (
1827 &gEfiAuthenticationInfoProtocolGuid
,
1828 EFI_NATIVE_INTERFACE
,
1829 &gIScsiAuthenticationInfo
1831 if (EFI_ERROR (Status
)) {
1839 IScsiCleanAttemptVariable ();
1842 IScsiConfigFormUnload (gIScsiIp4DriverBinding
.DriverBindingHandle
);
1845 if (mPrivate
!= NULL
) {
1846 FreePool (mPrivate
);
1851 gBS
->UninstallMultipleProtocolInterfaces (
1853 &gEfiIScsiInitiatorNameProtocolGuid
,
1854 &gIScsiInitiatorName
,
1859 EfiLibUninstallDriverBindingComponentName2 (
1860 &gIScsiIp6DriverBinding
,
1861 &gIScsiComponentName
,
1862 &gIScsiComponentName2
1866 EfiLibUninstallDriverBindingComponentName2 (
1867 &gIScsiIp4DriverBinding
,
1868 &gIScsiComponentName
,
1869 &gIScsiComponentName2