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
)) {
149 // Check whether the AIP instance has Network boot information block.
152 for (TypeIndex
= 0; TypeIndex
< InfoTypeBufferCount
; TypeIndex
++) {
153 if (CompareGuid (&InfoTypesBuffer
[TypeIndex
], &gEfiAdapterInfoNetworkBootGuid
)) {
159 FreePool (InfoTypesBuffer
);
165 // We now have network boot information block.
169 Status
= Aip
->GetInformation (Aip
, &gEfiAdapterInfoNetworkBootGuid
, &InfoBlock
, &InfoBlockSize
);
170 if (EFI_ERROR (Status
) || (InfoBlock
== NULL
)) {
175 // Check whether the network boot policy matches.
177 NetworkBoot
= (EFI_ADAPTER_INFO_NETWORK_BOOT
*)InfoBlock
;
178 NetworkBootPolicy
= PcdGet8 (PcdIScsiAIPNetworkBootPolicy
);
180 if (NetworkBootPolicy
== STOP_UEFI_ISCSI_IF_HBA_INSTALL_AIP
) {
181 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
))
198 FreePool (InfoBlock
);
202 Status
= EFI_SUCCESS
;
206 Status
= EFI_NOT_FOUND
;
209 if (InfoBlock
!= NULL
) {
210 FreePool (InfoBlock
);
213 if (AipHandleBuffer
!= NULL
) {
214 FreePool (AipHandleBuffer
);
221 Tests to see if this driver supports a given controller. This is the worker function for
222 IScsiIp4(6)DriverBindingSupported.
224 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
225 @param[in] ControllerHandle The handle of the controller to test. This handle
226 must support a protocol interface that supplies
227 an I/O abstraction to the driver.
228 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
229 parameter is ignored by device drivers, and is optional for bus
230 drivers. For bus drivers, if this parameter is not NULL, then
231 the bus driver must determine if the bus controller specified
232 by ControllerHandle and the child controller specified
233 by RemainingDevicePath are both supported by this
235 @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6.
237 @retval EFI_SUCCESS The device specified by ControllerHandle and
238 RemainingDevicePath is supported by the driver specified by This.
239 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
240 RemainingDevicePath is already being managed by the driver
242 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
243 RemainingDevicePath is not supported by the driver specified by This.
248 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
249 IN EFI_HANDLE ControllerHandle
,
250 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
,
255 EFI_GUID
*IScsiServiceBindingGuid
;
256 EFI_GUID
*TcpServiceBindingGuid
;
257 EFI_GUID
*DhcpServiceBindingGuid
;
258 EFI_GUID
*DnsServiceBindingGuid
;
260 if (IpVersion
== IP_VERSION_4
) {
261 IScsiServiceBindingGuid
= &gIScsiV4PrivateGuid
;
262 TcpServiceBindingGuid
= &gEfiTcp4ServiceBindingProtocolGuid
;
263 DhcpServiceBindingGuid
= &gEfiDhcp4ServiceBindingProtocolGuid
;
264 DnsServiceBindingGuid
= &gEfiDns4ServiceBindingProtocolGuid
;
266 IScsiServiceBindingGuid
= &gIScsiV6PrivateGuid
;
267 TcpServiceBindingGuid
= &gEfiTcp6ServiceBindingProtocolGuid
;
268 DhcpServiceBindingGuid
= &gEfiDhcp6ServiceBindingProtocolGuid
;
269 DnsServiceBindingGuid
= &gEfiDns6ServiceBindingProtocolGuid
;
272 Status
= gBS
->OpenProtocol (
274 IScsiServiceBindingGuid
,
276 This
->DriverBindingHandle
,
278 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
280 if (!EFI_ERROR (Status
)) {
281 return EFI_ALREADY_STARTED
;
284 Status
= gBS
->OpenProtocol (
286 TcpServiceBindingGuid
,
288 This
->DriverBindingHandle
,
290 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
292 if (EFI_ERROR (Status
)) {
293 return EFI_UNSUPPORTED
;
296 Status
= IScsiIsDevicePathSupported (RemainingDevicePath
);
297 if (EFI_ERROR (Status
)) {
298 return EFI_UNSUPPORTED
;
301 if (IScsiDhcpIsConfigured (ControllerHandle
, IpVersion
)) {
302 Status
= gBS
->OpenProtocol (
304 DhcpServiceBindingGuid
,
306 This
->DriverBindingHandle
,
308 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
310 if (EFI_ERROR (Status
)) {
311 return EFI_UNSUPPORTED
;
315 if (IScsiDnsIsConfigured (ControllerHandle
)) {
316 Status
= gBS
->OpenProtocol (
318 DnsServiceBindingGuid
,
320 This
->DriverBindingHandle
,
322 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
324 if (EFI_ERROR (Status
)) {
325 return EFI_UNSUPPORTED
;
333 Start to manage the controller. This is the worker function for
334 IScsiIp4(6)DriverBindingStart.
336 @param[in] Image Handle of the image.
337 @param[in] ControllerHandle Handle of the controller.
338 @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6.
340 @retval EFI_SUCCESS This driver was started.
341 @retval EFI_ALREADY_STARTED This driver is already running on this device.
342 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
343 @retval EFI_NOT_FOUND There is no sufficient information to establish
345 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
346 @retval EFI_DEVICE_ERROR Failed to get TCP connection device path.
347 @retval EFI_ACCESS_DENIED The protocol could not be removed from the Handle
348 because its interfaces are being used.
354 IN EFI_HANDLE ControllerHandle
,
359 ISCSI_DRIVER_DATA
*Private
;
361 LIST_ENTRY
*NextEntry
;
362 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
363 ISCSI_SESSION
*Session
;
365 EFI_EXT_SCSI_PASS_THRU_PROTOCOL
*ExistIScsiExtScsiPassThru
;
366 ISCSI_DRIVER_DATA
*ExistPrivate
;
367 UINT8
*AttemptConfigOrder
;
368 UINTN AttemptConfigOrderSize
;
370 EFI_HANDLE
*HandleBuffer
;
371 UINTN NumberOfHandles
;
372 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
373 EFI_GUID
*IScsiPrivateGuid
;
374 EFI_GUID
*TcpServiceBindingGuid
;
377 EFI_GUID
*ProtocolGuid
;
378 UINT8 NetworkBootPolicy
;
379 ISCSI_SESSION_CONFIG_NVDATA
*NvData
;
382 // Test to see if iSCSI driver supports the given controller.
385 if (IpVersion
== IP_VERSION_4
) {
386 IScsiPrivateGuid
= &gIScsiV4PrivateGuid
;
387 TcpServiceBindingGuid
= &gEfiTcp4ServiceBindingProtocolGuid
;
388 ProtocolGuid
= &gEfiTcp4ProtocolGuid
;
389 } else if (IpVersion
== IP_VERSION_6
) {
390 IScsiPrivateGuid
= &gIScsiV6PrivateGuid
;
391 TcpServiceBindingGuid
= &gEfiTcp6ServiceBindingProtocolGuid
;
392 ProtocolGuid
= &gEfiTcp6ProtocolGuid
;
394 return EFI_INVALID_PARAMETER
;
397 Status
= gBS
->OpenProtocol (
403 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
405 if (!EFI_ERROR (Status
)) {
406 return EFI_ALREADY_STARTED
;
409 Status
= gBS
->OpenProtocol (
411 TcpServiceBindingGuid
,
415 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
417 if (EFI_ERROR (Status
)) {
418 return EFI_UNSUPPORTED
;
421 NetworkBootPolicy
= PcdGet8 (PcdIScsiAIPNetworkBootPolicy
);
422 if (NetworkBootPolicy
== ALWAYS_USE_ISCSI_HBA_AND_IGNORE_UEFI_ISCSI
) {
426 if (NetworkBootPolicy
!= ALWAYS_USE_UEFI_ISCSI_AND_IGNORE_ISCSI_HBA
) {
428 // Check existing iSCSI AIP.
430 Status
= IScsiCheckAip ();
431 if (!EFI_ERROR (Status
)) {
433 // Find iSCSI AIP with specified network boot policy. return EFI_ABORTED.
440 // Record the incoming NIC info.
442 Status
= IScsiAddNic (ControllerHandle
, Image
);
443 if (EFI_ERROR (Status
)) {
448 // Create the instance private data.
450 Private
= IScsiCreateDriverData (Image
, ControllerHandle
);
451 if (Private
== NULL
) {
452 return EFI_OUT_OF_RESOURCES
;
456 // Create a underlayer child instance, but not need to configure it. Just open ChildHandle
457 // via BY_DRIVER. That is, establishing the relationship between ControllerHandle and ChildHandle.
458 // Therefore, when DisconnectController(), especially VLAN virtual controller handle,
459 // IScsiDriverBindingStop() will be called.
461 Status
= NetLibCreateServiceChild (
464 TcpServiceBindingGuid
,
465 &Private
->ChildHandle
468 if (EFI_ERROR (Status
)) {
472 Status
= gBS
->OpenProtocol (
473 Private
->ChildHandle
, /// Default Tcp child
478 EFI_OPEN_PROTOCOL_BY_DRIVER
481 if (EFI_ERROR (Status
)) {
486 // Always install private protocol no matter what happens later. We need to
487 // keep the relationship between ControllerHandle and ChildHandle.
489 Status
= gBS
->InstallProtocolInterface (
492 EFI_NATIVE_INTERFACE
,
493 &Private
->IScsiIdentifier
495 if (EFI_ERROR (Status
)) {
499 if (IpVersion
== IP_VERSION_4
) {
500 mPrivate
->Ipv6Flag
= FALSE
;
502 mPrivate
->Ipv6Flag
= TRUE
;
506 // Get the current iSCSI configuration data.
508 Status
= IScsiGetConfigData (Private
);
509 if (EFI_ERROR (Status
)) {
514 // If there is already a successul attempt, check whether this attempt is the
515 // first "enabled for MPIO" attempt. If not, still try the first attempt.
516 // In single path mode, try all attempts.
519 Status
= EFI_NOT_FOUND
;
521 if (mPrivate
->OneSessionEstablished
&& mPrivate
->EnableMpio
) {
522 AttemptConfigData
= NULL
;
523 NET_LIST_FOR_EACH (Entry
, &mPrivate
->AttemptConfigs
) {
524 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
525 if (AttemptConfigData
->SessionConfigData
.Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
530 if (AttemptConfigData
== NULL
) {
534 if (AttemptConfigData
->AttemptConfigIndex
== mPrivate
->BootSelectedIndex
) {
539 // Uninstall the original ExtScsiPassThru first.
543 // Locate all ExtScsiPassThru protocol instances.
545 Status
= gBS
->LocateHandleBuffer (
547 &gEfiExtScsiPassThruProtocolGuid
,
552 if (EFI_ERROR (Status
)) {
557 // Find ExtScsiPassThru protocol instance produced by this driver.
559 ExistIScsiExtScsiPassThru
= NULL
;
560 for (Index
= 0; Index
< NumberOfHandles
&& ExistIScsiExtScsiPassThru
== NULL
; Index
++) {
561 Status
= gBS
->HandleProtocol (
563 &gEfiDevicePathProtocolGuid
,
566 if (EFI_ERROR (Status
)) {
570 while (!IsDevicePathEnd (DevicePath
)) {
571 if ((DevicePath
->Type
== MESSAGING_DEVICE_PATH
) && (DevicePath
->SubType
== MSG_MAC_ADDR_DP
)) {
573 // Get the ExtScsiPassThru protocol instance.
575 Status
= gBS
->HandleProtocol (
577 &gEfiExtScsiPassThruProtocolGuid
,
578 (VOID
**)&ExistIScsiExtScsiPassThru
580 ASSERT_EFI_ERROR (Status
);
584 DevicePath
= NextDevicePathNode (DevicePath
);
588 FreePool (HandleBuffer
);
590 if (ExistIScsiExtScsiPassThru
== NULL
) {
591 Status
= EFI_NOT_FOUND
;
595 ExistPrivate
= ISCSI_DRIVER_DATA_FROM_EXT_SCSI_PASS_THRU (ExistIScsiExtScsiPassThru
);
597 Status
= gBS
->UninstallProtocolInterface (
598 ExistPrivate
->ExtScsiPassThruHandle
,
599 &gEfiExtScsiPassThruProtocolGuid
,
600 &ExistPrivate
->IScsiExtScsiPassThru
602 if (EFI_ERROR (Status
)) {
608 // Install the Ext SCSI PASS THRU protocol.
610 Status
= gBS
->InstallProtocolInterface (
611 &Private
->ExtScsiPassThruHandle
,
612 &gEfiExtScsiPassThruProtocolGuid
,
613 EFI_NATIVE_INTERFACE
,
614 &Private
->IScsiExtScsiPassThru
616 if (EFI_ERROR (Status
)) {
622 NET_LIST_FOR_EACH_SAFE (Entry
, NextEntry
, &mPrivate
->AttemptConfigs
) {
623 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
625 // Don't process the attempt that does not associate with the current NIC or
626 // this attempt is disabled or established.
628 if ((AttemptConfigData
->NicIndex
!= mPrivate
->CurrentNic
) ||
629 (AttemptConfigData
->SessionConfigData
.Enabled
== ISCSI_DISABLED
) ||
630 AttemptConfigData
->ValidPath
)
636 // In multipath mode, don't process attempts configured for single path.
637 // In default single path mode, don't process attempts configured for multipath.
639 if ((mPrivate
->EnableMpio
&&
640 (AttemptConfigData
->SessionConfigData
.Enabled
!= ISCSI_ENABLED_FOR_MPIO
)) ||
641 (!mPrivate
->EnableMpio
&&
642 (AttemptConfigData
->SessionConfigData
.Enabled
!= ISCSI_ENABLED
)))
648 // Don't process the attempt that fails to get the init/target information from DHCP.
650 if (AttemptConfigData
->SessionConfigData
.InitiatorInfoFromDhcp
&&
651 !AttemptConfigData
->DhcpSuccess
)
653 if (!mPrivate
->EnableMpio
&& (mPrivate
->ValidSinglePathCount
> 0)) {
654 mPrivate
->ValidSinglePathCount
--;
661 // Don't process the autoconfigure path if it is already established.
663 if ((AttemptConfigData
->SessionConfigData
.IpMode
== IP_MODE_AUTOCONFIG
) &&
664 AttemptConfigData
->AutoConfigureSuccess
)
670 // Don't process the attempt if its IP mode is not in the current IP version.
672 if (!mPrivate
->Ipv6Flag
) {
673 if (AttemptConfigData
->SessionConfigData
.IpMode
== IP_MODE_IP6
) {
677 if ((AttemptConfigData
->SessionConfigData
.IpMode
== IP_MODE_AUTOCONFIG
) &&
678 (AttemptConfigData
->AutoConfigureMode
== IP_MODE_AUTOCONFIG_IP6
))
683 if (AttemptConfigData
->SessionConfigData
.IpMode
== IP_MODE_IP4
) {
687 if ((AttemptConfigData
->SessionConfigData
.IpMode
== IP_MODE_AUTOCONFIG
) &&
688 (AttemptConfigData
->AutoConfigureMode
== IP_MODE_AUTOCONFIG_IP4
))
695 // Fill in the Session and init it.
697 Session
= (ISCSI_SESSION
*)AllocateZeroPool (sizeof (ISCSI_SESSION
));
698 if (Session
== NULL
) {
699 Status
= EFI_OUT_OF_RESOURCES
;
703 Session
->Private
= Private
;
704 Session
->ConfigData
= AttemptConfigData
;
705 Session
->AuthType
= AttemptConfigData
->AuthenticationType
;
708 mPrivate
->PortString
,
709 (UINTN
)ISCSI_NAME_IFR_MAX_SIZE
,
711 (UINTN
)AttemptConfigData
->AttemptConfigIndex
714 if (Session
->AuthType
== ISCSI_AUTH_TYPE_CHAP
) {
715 Session
->AuthData
.CHAP
.AuthConfig
= &AttemptConfigData
->AuthConfigData
.CHAP
;
718 IScsiSessionInit (Session
, FALSE
);
721 // Try to login and create an iSCSI session according to the configuration.
723 Status
= IScsiSessionLogin (Session
);
724 if (Status
== EFI_MEDIA_CHANGED
) {
726 // The specified target is not available, and the redirection information is
727 // received. Login the session again with the updated target address.
729 Status
= IScsiSessionLogin (Session
);
730 } else if (Status
== EFI_NOT_READY
) {
731 Status
= IScsiSessionReLogin (Session
);
735 // Restore the original user setting which specifies the proxy/virtual iSCSI target to NV region.
737 NvData
= &AttemptConfigData
->SessionConfigData
;
738 if (NvData
->RedirectFlag
) {
739 NvData
->TargetPort
= NvData
->OriginalTargetPort
;
740 CopyMem (&NvData
->TargetIp
, &NvData
->OriginalTargetIp
, sizeof (EFI_IP_ADDRESS
));
741 NvData
->RedirectFlag
= FALSE
;
744 mPrivate
->PortString
,
745 &gEfiIScsiInitiatorNameProtocolGuid
,
746 ISCSI_CONFIG_VAR_ATTR
,
747 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA
),
752 if (EFI_ERROR (Status
)) {
754 // In Single path mode, only the successful attempt will be recorded in iBFT;
755 // in multi-path mode, all the attempt entries in MPIO will be recorded in iBFT.
757 if (!mPrivate
->EnableMpio
&& (mPrivate
->ValidSinglePathCount
> 0)) {
758 mPrivate
->ValidSinglePathCount
--;
763 AttemptConfigData
->ValidPath
= TRUE
;
766 // Do not record the attempt in iBFT if it login with KRB5.
767 // TODO: record KRB5 attempt information in the iSCSI device path.
769 if (Session
->AuthType
== ISCSI_AUTH_TYPE_KRB
) {
770 if (!mPrivate
->EnableMpio
&& (mPrivate
->ValidSinglePathCount
> 0)) {
771 mPrivate
->ValidSinglePathCount
--;
774 AttemptConfigData
->ValidiBFTPath
= FALSE
;
776 AttemptConfigData
->ValidiBFTPath
= TRUE
;
780 // IScsi session success. Update the attempt state to NVR.
782 if (AttemptConfigData
->SessionConfigData
.IpMode
== IP_MODE_AUTOCONFIG
) {
783 AttemptConfigData
->AutoConfigureSuccess
= TRUE
;
787 mPrivate
->PortString
,
788 &gEfiIScsiInitiatorNameProtocolGuid
,
789 ISCSI_CONFIG_VAR_ATTR
,
790 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA
),
795 // Select the first login session. Abort others.
797 if (Private
->Session
== NULL
) {
798 Private
->Session
= Session
;
799 BootSelected
= AttemptConfigData
->AttemptConfigIndex
;
801 // Don't validate other attempt in multipath mode if one is success.
803 if (mPrivate
->EnableMpio
) {
807 IScsiSessionAbort (Session
);
814 // All attempts configured for this driver instance are not valid.
816 if (Private
->Session
== NULL
) {
817 Status
= gBS
->UninstallProtocolInterface (
818 Private
->ExtScsiPassThruHandle
,
819 &gEfiExtScsiPassThruProtocolGuid
,
820 &Private
->IScsiExtScsiPassThru
822 ASSERT_EFI_ERROR (Status
);
823 Private
->ExtScsiPassThruHandle
= NULL
;
826 // Reinstall the original ExtScsiPassThru back.
828 if (mPrivate
->OneSessionEstablished
&& (ExistPrivate
!= NULL
)) {
829 Status
= gBS
->InstallProtocolInterface (
830 &ExistPrivate
->ExtScsiPassThruHandle
,
831 &gEfiExtScsiPassThruProtocolGuid
,
832 EFI_NATIVE_INTERFACE
,
833 &ExistPrivate
->IScsiExtScsiPassThru
835 if (EFI_ERROR (Status
)) {
842 Status
= EFI_NOT_FOUND
;
849 // More than one attempt successes.
851 if ((Private
->Session
!= NULL
) && mPrivate
->OneSessionEstablished
) {
852 AttemptConfigOrder
= IScsiGetVariableAndSize (
855 &AttemptConfigOrderSize
857 if (AttemptConfigOrder
== NULL
) {
861 for (Index
= 0; Index
< AttemptConfigOrderSize
/ sizeof (UINT8
); Index
++) {
862 if ((AttemptConfigOrder
[Index
] == mPrivate
->BootSelectedIndex
) ||
863 (AttemptConfigOrder
[Index
] == BootSelected
))
869 if (mPrivate
->EnableMpio
) {
871 // Use the attempt in earlier order. Abort the later one in MPIO.
873 if (AttemptConfigOrder
[Index
] == mPrivate
->BootSelectedIndex
) {
874 IScsiSessionAbort (Private
->Session
);
875 FreePool (Private
->Session
);
876 Private
->Session
= NULL
;
877 gBS
->UninstallProtocolInterface (
878 Private
->ExtScsiPassThruHandle
,
879 &gEfiExtScsiPassThruProtocolGuid
,
880 &Private
->IScsiExtScsiPassThru
882 Private
->ExtScsiPassThruHandle
= NULL
;
885 // Reinstall the original ExtScsiPassThru back.
887 Status
= gBS
->InstallProtocolInterface (
888 &ExistPrivate
->ExtScsiPassThruHandle
,
889 &gEfiExtScsiPassThruProtocolGuid
,
890 EFI_NATIVE_INTERFACE
,
891 &ExistPrivate
->IScsiExtScsiPassThru
893 if (EFI_ERROR (Status
)) {
899 if (AttemptConfigOrder
[Index
] != BootSelected
) {
903 mPrivate
->BootSelectedIndex
= BootSelected
;
905 // Clear the resource in ExistPrivate.
907 gBS
->UninstallProtocolInterface (
908 ExistPrivate
->Controller
,
910 &ExistPrivate
->IScsiIdentifier
913 IScsiRemoveNic (ExistPrivate
->Controller
);
914 if (ExistPrivate
->Session
!= NULL
) {
915 IScsiSessionAbort (ExistPrivate
->Session
);
918 if (ExistPrivate
->DevicePath
!= NULL
) {
919 Status
= gBS
->UninstallProtocolInterface (
920 ExistPrivate
->ExtScsiPassThruHandle
,
921 &gEfiDevicePathProtocolGuid
,
922 ExistPrivate
->DevicePath
924 if (EFI_ERROR (Status
)) {
928 FreePool (ExistPrivate
->DevicePath
);
931 gBS
->CloseEvent (ExistPrivate
->ExitBootServiceEvent
);
932 FreePool (ExistPrivate
);
936 // Use the attempt in earlier order as boot selected in single path mode.
938 if (AttemptConfigOrder
[Index
] == mPrivate
->BootSelectedIndex
) {
945 mPrivate
->OneSessionEstablished
= TRUE
;
946 mPrivate
->BootSelectedIndex
= BootSelected
;
950 // Duplicate the Session's tcp connection device path. The source port field
951 // will be set to zero as one iSCSI session is comprised of several iSCSI
954 Private
->DevicePath
= IScsiGetTcpConnDevicePath (Private
->Session
);
955 if (Private
->DevicePath
== NULL
) {
956 Status
= EFI_DEVICE_ERROR
;
961 // Install the updated device path onto the ExtScsiPassThruHandle.
963 Status
= gBS
->InstallProtocolInterface (
964 &Private
->ExtScsiPassThruHandle
,
965 &gEfiDevicePathProtocolGuid
,
966 EFI_NATIVE_INTERFACE
,
969 if (EFI_ERROR (Status
)) {
974 // ISCSI children should share the default Tcp child, just open the default Tcp child via BY_CHILD_CONTROLLER.
976 Status
= gBS
->OpenProtocol (
977 Private
->ChildHandle
, /// Default Tcp child
981 Private
->ExtScsiPassThruHandle
,
982 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
984 if (EFI_ERROR (Status
)) {
985 gBS
->UninstallMultipleProtocolInterfaces (
986 Private
->ExtScsiPassThruHandle
,
987 &gEfiExtScsiPassThruProtocolGuid
,
988 &Private
->IScsiExtScsiPassThru
,
989 &gEfiDevicePathProtocolGuid
,
1000 // Update/Publish the iSCSI Boot Firmware Table.
1002 if (mPrivate
->BootSelectedIndex
!= 0) {
1003 IScsiPublishIbft ();
1010 if (Private
->Session
!= NULL
) {
1011 IScsiSessionAbort (Private
->Session
);
1018 Stops a device controller or a bus controller. This is the worker function for
1019 IScsiIp4(6)DriverBindingStop.
1021 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
1022 @param[in] ControllerHandle A handle to the device being stopped. The handle must
1023 support a bus specific I/O protocol for the driver
1024 to use to stop the device.
1025 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
1026 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
1027 if NumberOfChildren is 0.
1028 @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6.
1030 @retval EFI_SUCCESS The device was stopped.
1031 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
1032 @retval EFI_INVALID_PARAMETER Child handle is NULL.
1033 @retval EFI_ACCESS_DENIED The protocol could not be removed from the Handle
1034 because its interfaces are being used.
1040 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1041 IN EFI_HANDLE ControllerHandle
,
1042 IN UINTN NumberOfChildren
,
1043 IN EFI_HANDLE
*ChildHandleBuffer OPTIONAL
,
1047 EFI_HANDLE IScsiController
;
1049 ISCSI_PRIVATE_PROTOCOL
*IScsiIdentifier
;
1050 ISCSI_DRIVER_DATA
*Private
;
1051 EFI_EXT_SCSI_PASS_THRU_PROTOCOL
*PassThru
;
1052 ISCSI_CONNECTION
*Conn
;
1053 EFI_GUID
*ProtocolGuid
;
1054 EFI_GUID
*TcpServiceBindingGuid
;
1055 EFI_GUID
*TcpProtocolGuid
;
1057 if (NumberOfChildren
!= 0) {
1059 // We should have only one child.
1061 Status
= gBS
->OpenProtocol (
1062 ChildHandleBuffer
[0],
1063 &gEfiExtScsiPassThruProtocolGuid
,
1065 This
->DriverBindingHandle
,
1067 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1069 if (EFI_ERROR (Status
)) {
1070 return EFI_DEVICE_ERROR
;
1073 Private
= ISCSI_DRIVER_DATA_FROM_EXT_SCSI_PASS_THRU (PassThru
);
1074 Conn
= NET_LIST_HEAD (&Private
->Session
->Conns
, ISCSI_CONNECTION
, Link
);
1077 // Previously the TCP protocol is opened BY_CHILD_CONTROLLER. Just close
1078 // the protocol here, but do not uninstall the device path protocol and
1079 // EXT SCSI PASS THRU protocol installed on ExtScsiPassThruHandle.
1081 if (IpVersion
== IP_VERSION_4
) {
1082 ProtocolGuid
= &gEfiTcp4ProtocolGuid
;
1084 ProtocolGuid
= &gEfiTcp6ProtocolGuid
;
1087 gBS
->CloseProtocol (
1088 Private
->ChildHandle
,
1091 Private
->ExtScsiPassThruHandle
1094 gBS
->CloseProtocol (
1098 Private
->ExtScsiPassThruHandle
1105 // Get the handle of the controller we are controlling.
1107 if (IpVersion
== IP_VERSION_4
) {
1108 ProtocolGuid
= &gIScsiV4PrivateGuid
;
1109 TcpProtocolGuid
= &gEfiTcp4ProtocolGuid
;
1110 TcpServiceBindingGuid
= &gEfiTcp4ServiceBindingProtocolGuid
;
1112 ProtocolGuid
= &gIScsiV6PrivateGuid
;
1113 TcpProtocolGuid
= &gEfiTcp6ProtocolGuid
;
1114 TcpServiceBindingGuid
= &gEfiTcp6ServiceBindingProtocolGuid
;
1117 IScsiController
= NetLibGetNicHandle (ControllerHandle
, TcpProtocolGuid
);
1118 if (IScsiController
== NULL
) {
1122 Status
= gBS
->OpenProtocol (
1125 (VOID
**)&IScsiIdentifier
,
1126 This
->DriverBindingHandle
,
1128 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1130 if (EFI_ERROR (Status
)) {
1131 return EFI_DEVICE_ERROR
;
1134 Private
= ISCSI_DRIVER_DATA_FROM_IDENTIFIER (IScsiIdentifier
);
1135 ASSERT (Private
!= NULL
);
1137 if (Private
->ChildHandle
!= NULL
) {
1138 Status
= gBS
->CloseProtocol (
1139 Private
->ChildHandle
,
1141 This
->DriverBindingHandle
,
1145 ASSERT (!EFI_ERROR (Status
));
1147 Status
= NetLibDestroyServiceChild (
1149 This
->DriverBindingHandle
,
1150 TcpServiceBindingGuid
,
1151 Private
->ChildHandle
1154 ASSERT (!EFI_ERROR (Status
));
1157 gBS
->UninstallProtocolInterface (
1160 &Private
->IScsiIdentifier
1166 IScsiRemoveNic (IScsiController
);
1169 // Update the iSCSI Boot Firmware Table.
1171 IScsiPublishIbft ();
1173 if (Private
->Session
!= NULL
) {
1174 IScsiSessionAbort (Private
->Session
);
1177 Status
= IScsiCleanDriverData (Private
);
1179 if (EFI_ERROR (Status
)) {
1187 Tests to see if this driver supports a given controller. If a child device is provided,
1188 it tests to see if this driver supports creating a handle for the specified child device.
1190 This function checks to see if the driver specified by This supports the device specified by
1191 ControllerHandle. Drivers typically use the device path attached to
1192 ControllerHandle and/or the services from the bus I/O abstraction attached to
1193 ControllerHandle to determine if the driver supports ControllerHandle. This function
1194 may be called many times during platform initialization. In order to reduce boot times, the tests
1195 performed by this function must be very small and take as little time as possible to execute. This
1196 function must not change the state of any hardware devices, and this function must be aware that the
1197 device specified by ControllerHandle may already be managed by the same driver or a
1198 different driver. This function must match its calls to AllocatePages() with FreePages(),
1199 AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
1200 Since ControllerHandle may have been previously started by the same driver, if a protocol is
1201 already in the opened state, then it must not be closed with CloseProtocol(). This is required
1202 to guarantee the state of ControllerHandle is not modified by this function.
1204 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
1205 @param[in] ControllerHandle The handle of the controller to test. This handle
1206 must support a protocol interface that supplies
1207 an I/O abstraction to the driver.
1208 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
1209 parameter is ignored by device drivers, and is optional for bus
1210 drivers. For bus drivers, if this parameter is not NULL, then
1211 the bus driver must determine if the bus controller specified
1212 by ControllerHandle and the child controller specified
1213 by RemainingDevicePath are both supported by this
1216 @retval EFI_SUCCESS The device specified by ControllerHandle and
1217 RemainingDevicePath is supported by the driver specified by This.
1218 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
1219 RemainingDevicePath is already managed by the driver
1221 @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
1222 RemainingDevicePath is already managed by a different
1223 driver or an application that requires exclusive access.
1224 Currently not implemented.
1225 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
1226 RemainingDevicePath is not supported by the driver specified by This.
1230 IScsiIp4DriverBindingSupported (
1231 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1232 IN EFI_HANDLE ControllerHandle
,
1233 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
1236 return IScsiSupported (
1239 RemainingDevicePath
,
1245 Starts a device controller or a bus controller.
1247 The Start() function is designed to be invoked from the EFI boot service ConnectController().
1248 As a result, much of the error checking on the parameters to Start() has been moved into this
1249 common boot service. It is legal to call Start() from other locations,
1250 but the following calling restrictions must be followed or the system behavior will not be deterministic.
1251 1. ControllerHandle must be a valid EFI_HANDLE.
1252 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
1253 EFI_DEVICE_PATH_PROTOCOL.
1254 3. Prior to calling Start(), the Supported() function for the driver specified by This must
1255 have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
1257 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
1258 @param[in] ControllerHandle The handle of the controller to start. This handle
1259 must support a protocol interface that supplies
1260 an I/O abstraction to the driver.
1261 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
1262 parameter is ignored by device drivers, and is optional for bus
1263 drivers. For a bus driver, if this parameter is NULL, then handles
1264 for all the children of Controller are created by this driver.
1265 If this parameter is not NULL and the first Device Path Node is
1266 not the End of Device Path Node, then only the handle for the
1267 child device specified by the first Device Path Node of
1268 RemainingDevicePath is created by this driver.
1269 If the first Device Path Node of RemainingDevicePath is
1270 the End of Device Path Node, no child handle is created by this
1273 @retval EFI_SUCCESS The device was started.
1274 @retval EFI_DEVICE_ERROR The device could not be started due to a device error. Currently not implemented.
1275 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
1276 @retval Others The driver failed to start the device.
1281 IScsiIp4DriverBindingStart (
1282 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1283 IN EFI_HANDLE ControllerHandle
,
1284 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
1289 Status
= IScsiStart (This
->DriverBindingHandle
, ControllerHandle
, IP_VERSION_4
);
1290 if (Status
== EFI_ALREADY_STARTED
) {
1291 Status
= EFI_SUCCESS
;
1298 Stops a device controller or a bus controller.
1300 The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
1301 As a result, much of the error checking on the parameters to Stop() has been moved
1302 into this common boot service. It is legal to call Stop() from other locations,
1303 but the following calling restrictions must be followed or the system behavior will not be deterministic.
1304 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
1305 same driver's Start() function.
1306 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
1307 EFI_HANDLE. In addition, all of these handles must have been created in this driver's
1308 Start() function, and the Start() function must have called OpenProtocol() on
1309 ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
1311 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
1312 @param[in] ControllerHandle A handle to the device being stopped. The handle must
1313 support a bus specific I/O protocol for the driver
1314 to use to stop the device.
1315 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
1316 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
1317 if NumberOfChildren is 0.
1319 @retval EFI_SUCCESS The device was stopped.
1320 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
1325 IScsiIp4DriverBindingStop (
1326 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1327 IN EFI_HANDLE ControllerHandle
,
1328 IN UINTN NumberOfChildren
,
1329 IN EFI_HANDLE
*ChildHandleBuffer OPTIONAL
1342 Tests to see if this driver supports a given controller. If a child device is provided,
1343 it tests to see if this driver supports creating a handle for the specified child device.
1345 This function checks to see if the driver specified by This supports the device specified by
1346 ControllerHandle. Drivers typically use the device path attached to
1347 ControllerHandle and/or the services from the bus I/O abstraction attached to
1348 ControllerHandle to determine if the driver supports ControllerHandle. This function
1349 may be called many times during platform initialization. In order to reduce boot times, the tests
1350 performed by this function must be very small and take as little time as possible to execute. This
1351 function must not change the state of any hardware devices, and this function must be aware that the
1352 device specified by ControllerHandle may already be managed by the same driver or a
1353 different driver. This function must match its calls to AllocatePages() with FreePages(),
1354 AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
1355 Since ControllerHandle may have been previously started by the same driver, if a protocol is
1356 already in the opened state, then it must not be closed with CloseProtocol(). This is required
1357 to guarantee the state of ControllerHandle is not modified by this function.
1359 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
1360 @param[in] ControllerHandle The handle of the controller to test. This handle
1361 must support a protocol interface that supplies
1362 an I/O abstraction to the driver.
1363 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
1364 parameter is ignored by device drivers, and is optional for bus
1365 drivers. For bus drivers, if this parameter is not NULL, then
1366 the bus driver must determine if the bus controller specified
1367 by ControllerHandle and the child controller specified
1368 by RemainingDevicePath are both supported by this
1371 @retval EFI_SUCCESS The device specified by ControllerHandle and
1372 RemainingDevicePath is supported by the driver specified by This.
1373 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
1374 RemainingDevicePath is already managed by the driver
1376 @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
1377 RemainingDevicePath is already managed by a different
1378 driver or an application that requires exclusive access.
1379 Currently not implemented.
1380 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
1381 RemainingDevicePath is not supported by the driver specified by This.
1385 IScsiIp6DriverBindingSupported (
1386 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1387 IN EFI_HANDLE ControllerHandle
,
1388 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
1391 return IScsiSupported (
1394 RemainingDevicePath
,
1400 Starts a device controller or a bus controller.
1402 The Start() function is designed to be invoked from the EFI boot service ConnectController().
1403 As a result, much of the error checking on the parameters to Start() has been moved into this
1404 common boot service. It is legal to call Start() from other locations,
1405 but the following calling restrictions must be followed or the system behavior will not be deterministic.
1406 1. ControllerHandle must be a valid EFI_HANDLE.
1407 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
1408 EFI_DEVICE_PATH_PROTOCOL.
1409 3. Prior to calling Start(), the Supported() function for the driver specified by This must
1410 have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
1412 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
1413 @param[in] ControllerHandle The handle of the controller to start. This handle
1414 must support a protocol interface that supplies
1415 an I/O abstraction to the driver.
1416 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
1417 parameter is ignored by device drivers, and is optional for bus
1418 drivers. For a bus driver, if this parameter is NULL, then handles
1419 for all the children of Controller are created by this driver.
1420 If this parameter is not NULL and the first Device Path Node is
1421 not the End of Device Path Node, then only the handle for the
1422 child device specified by the first Device Path Node of
1423 RemainingDevicePath is created by this driver.
1424 If the first Device Path Node of RemainingDevicePath is
1425 the End of Device Path Node, no child handle is created by this
1428 @retval EFI_SUCCESS The device was started.
1429 @retval EFI_DEVICE_ERROR The device could not be started due to a device error. Currently not implemented.
1430 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
1431 @retval Others The driver failed to start the device.
1436 IScsiIp6DriverBindingStart (
1437 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1438 IN EFI_HANDLE ControllerHandle
,
1439 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
1444 Status
= IScsiStart (This
->DriverBindingHandle
, ControllerHandle
, IP_VERSION_6
);
1445 if (Status
== EFI_ALREADY_STARTED
) {
1446 Status
= EFI_SUCCESS
;
1453 Stops a device controller or a bus controller.
1455 The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
1456 As a result, much of the error checking on the parameters to Stop() has been moved
1457 into this common boot service. It is legal to call Stop() from other locations,
1458 but the following calling restrictions must be followed or the system behavior will not be deterministic.
1459 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
1460 same driver's Start() function.
1461 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
1462 EFI_HANDLE. In addition, all of these handles must have been created in this driver's
1463 Start() function, and the Start() function must have called OpenProtocol() on
1464 ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
1466 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
1467 @param[in] ControllerHandle A handle to the device being stopped. The handle must
1468 support a bus specific I/O protocol for the driver
1469 to use to stop the device.
1470 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
1471 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
1472 if NumberOfChildren is 0.
1474 @retval EFI_SUCCESS The device was stopped.
1475 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
1480 IScsiIp6DriverBindingStop (
1481 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1482 IN EFI_HANDLE ControllerHandle
,
1483 IN UINTN NumberOfChildren
,
1484 IN EFI_HANDLE
*ChildHandleBuffer OPTIONAL
1497 Unload the iSCSI driver.
1499 @param[in] ImageHandle The handle of the driver image.
1501 @retval EFI_SUCCESS The driver is unloaded.
1502 @retval EFI_DEVICE_ERROR An unexpected error occurred.
1508 IN EFI_HANDLE ImageHandle
1512 UINTN DeviceHandleCount
;
1513 EFI_HANDLE
*DeviceHandleBuffer
;
1515 EFI_COMPONENT_NAME_PROTOCOL
*ComponentName
;
1516 EFI_COMPONENT_NAME2_PROTOCOL
*ComponentName2
;
1519 // Try to disconnect the driver from the devices it's controlling.
1521 Status
= gBS
->LocateHandleBuffer (
1528 if (EFI_ERROR (Status
)) {
1533 // Disconnect the iSCSI4 driver from the controlled device.
1535 for (Index
= 0; Index
< DeviceHandleCount
; Index
++) {
1536 Status
= IScsiTestManagedDevice (
1537 DeviceHandleBuffer
[Index
],
1538 gIScsiIp4DriverBinding
.DriverBindingHandle
,
1539 &gEfiTcp4ProtocolGuid
1542 if (EFI_ERROR (Status
)) {
1546 Status
= gBS
->DisconnectController (
1547 DeviceHandleBuffer
[Index
],
1548 gIScsiIp4DriverBinding
.DriverBindingHandle
,
1551 if (EFI_ERROR (Status
)) {
1557 // Disconnect the iSCSI6 driver from the controlled device.
1559 for (Index
= 0; Index
< DeviceHandleCount
; Index
++) {
1560 Status
= IScsiTestManagedDevice (
1561 DeviceHandleBuffer
[Index
],
1562 gIScsiIp6DriverBinding
.DriverBindingHandle
,
1563 &gEfiTcp6ProtocolGuid
1565 if (EFI_ERROR (Status
)) {
1569 Status
= gBS
->DisconnectController (
1570 DeviceHandleBuffer
[Index
],
1571 gIScsiIp6DriverBinding
.DriverBindingHandle
,
1574 if (EFI_ERROR (Status
)) {
1580 // Unload the iSCSI configuration form.
1582 Status
= IScsiConfigFormUnload (gIScsiIp4DriverBinding
.DriverBindingHandle
);
1583 if (EFI_ERROR (Status
)) {
1588 // Uninstall the protocols installed by iSCSI driver.
1590 Status
= gBS
->UninstallMultipleProtocolInterfaces (
1592 &gEfiAuthenticationInfoProtocolGuid
,
1593 &gIScsiAuthenticationInfo
,
1596 if (EFI_ERROR (Status
)) {
1600 if (gIScsiControllerNameTable
!= NULL
) {
1601 Status
= FreeUnicodeStringTable (gIScsiControllerNameTable
);
1602 if (EFI_ERROR (Status
)) {
1606 gIScsiControllerNameTable
= NULL
;
1610 // Uninstall the ComponentName and ComponentName2 protocol from iSCSI4 driver binding handle
1611 // if it has been installed.
1613 Status
= gBS
->HandleProtocol (
1614 gIScsiIp4DriverBinding
.DriverBindingHandle
,
1615 &gEfiComponentNameProtocolGuid
,
1616 (VOID
**)&ComponentName
1618 if (!EFI_ERROR (Status
)) {
1619 Status
= gBS
->UninstallMultipleProtocolInterfaces (
1620 gIScsiIp4DriverBinding
.DriverBindingHandle
,
1621 &gEfiComponentNameProtocolGuid
,
1625 if (EFI_ERROR (Status
)) {
1630 Status
= gBS
->HandleProtocol (
1631 gIScsiIp4DriverBinding
.DriverBindingHandle
,
1632 &gEfiComponentName2ProtocolGuid
,
1633 (VOID
**)&ComponentName2
1635 if (!EFI_ERROR (Status
)) {
1636 gBS
->UninstallMultipleProtocolInterfaces (
1637 gIScsiIp4DriverBinding
.DriverBindingHandle
,
1638 &gEfiComponentName2ProtocolGuid
,
1642 if (EFI_ERROR (Status
)) {
1648 // Uninstall the ComponentName and ComponentName2 protocol from iSCSI6 driver binding handle
1649 // if it has been installed.
1651 Status
= gBS
->HandleProtocol (
1652 gIScsiIp6DriverBinding
.DriverBindingHandle
,
1653 &gEfiComponentNameProtocolGuid
,
1654 (VOID
**)&ComponentName
1656 if (!EFI_ERROR (Status
)) {
1657 Status
= gBS
->UninstallMultipleProtocolInterfaces (
1658 gIScsiIp6DriverBinding
.DriverBindingHandle
,
1659 &gEfiComponentNameProtocolGuid
,
1663 if (EFI_ERROR (Status
)) {
1668 Status
= gBS
->HandleProtocol (
1669 gIScsiIp6DriverBinding
.DriverBindingHandle
,
1670 &gEfiComponentName2ProtocolGuid
,
1671 (VOID
**)&ComponentName2
1673 if (!EFI_ERROR (Status
)) {
1674 gBS
->UninstallMultipleProtocolInterfaces (
1675 gIScsiIp6DriverBinding
.DriverBindingHandle
,
1676 &gEfiComponentName2ProtocolGuid
,
1680 if (EFI_ERROR (Status
)) {
1686 // Uninstall the IScsiInitiatorNameProtocol and all the driver binding protocols.
1688 Status
= gBS
->UninstallMultipleProtocolInterfaces (
1689 gIScsiIp4DriverBinding
.DriverBindingHandle
,
1690 &gEfiDriverBindingProtocolGuid
,
1691 &gIScsiIp4DriverBinding
,
1692 &gEfiIScsiInitiatorNameProtocolGuid
,
1693 &gIScsiInitiatorName
,
1696 if (EFI_ERROR (Status
)) {
1700 Status
= gBS
->UninstallMultipleProtocolInterfaces (
1701 gIScsiIp6DriverBinding
.DriverBindingHandle
,
1702 &gEfiDriverBindingProtocolGuid
,
1703 &gIScsiIp6DriverBinding
,
1709 if (DeviceHandleBuffer
!= NULL
) {
1710 FreePool (DeviceHandleBuffer
);
1717 This is the declaration of an EFI image entry point. This entry point is
1718 the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including
1719 both device drivers and bus drivers.
1721 The entry point for iSCSI driver which initializes the global variables and
1722 installs the driver binding, component name protocol, iSCSI initiator name
1723 protocol and Authentication Info protocol on its image.
1725 @param[in] ImageHandle The firmware allocated handle for the UEFI image.
1726 @param[in] SystemTable A pointer to the EFI System Table.
1728 @retval EFI_SUCCESS The operation completed successfully.
1729 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
1734 IScsiDriverEntryPoint (
1735 IN EFI_HANDLE ImageHandle
,
1736 IN EFI_SYSTEM_TABLE
*SystemTable
1740 EFI_ISCSI_INITIATOR_NAME_PROTOCOL
*IScsiInitiatorName
;
1741 EFI_AUTHENTICATION_INFO_PROTOCOL
*AuthenticationInfo
;
1744 // There should be only one EFI_ISCSI_INITIATOR_NAME_PROTOCOL.
1746 Status
= gBS
->LocateProtocol (
1747 &gEfiIScsiInitiatorNameProtocolGuid
,
1749 (VOID
**)&IScsiInitiatorName
1751 if (!EFI_ERROR (Status
)) {
1752 return EFI_ACCESS_DENIED
;
1756 // Initialize the EFI Driver Library.
1758 Status
= EfiLibInstallDriverBindingComponentName2 (
1761 &gIScsiIp4DriverBinding
,
1763 &gIScsiComponentName
,
1764 &gIScsiComponentName2
1766 if (EFI_ERROR (Status
)) {
1770 Status
= EfiLibInstallDriverBindingComponentName2 (
1773 &gIScsiIp6DriverBinding
,
1775 &gIScsiComponentName
,
1776 &gIScsiComponentName2
1778 if (EFI_ERROR (Status
)) {
1783 // Install the iSCSI Initiator Name Protocol.
1785 Status
= gBS
->InstallProtocolInterface (
1787 &gEfiIScsiInitiatorNameProtocolGuid
,
1788 EFI_NATIVE_INTERFACE
,
1789 &gIScsiInitiatorName
1791 if (EFI_ERROR (Status
)) {
1796 // Create the private data structures.
1798 IScsiCHAPInitHashList ();
1800 mPrivate
= AllocateZeroPool (sizeof (ISCSI_PRIVATE_DATA
));
1801 if (mPrivate
== NULL
) {
1802 Status
= EFI_OUT_OF_RESOURCES
;
1806 InitializeListHead (&mPrivate
->NicInfoList
);
1807 InitializeListHead (&mPrivate
->AttemptConfigs
);
1810 // Initialize the configuration form of iSCSI.
1812 Status
= IScsiConfigFormInit (gIScsiIp4DriverBinding
.DriverBindingHandle
);
1813 if (EFI_ERROR (Status
)) {
1818 // Create the Maximum Attempts.
1820 Status
= IScsiCreateAttempts (PcdGet8 (PcdMaxIScsiAttemptNumber
));
1821 if (EFI_ERROR (Status
)) {
1826 // Create Keywords for all the Attempts.
1828 Status
= IScsiCreateKeywords (PcdGet8 (PcdMaxIScsiAttemptNumber
));
1829 if (EFI_ERROR (Status
)) {
1834 // There should be only one EFI_AUTHENTICATION_INFO_PROTOCOL. If already exists,
1835 // do not produce the protocol instance.
1837 Status
= gBS
->LocateProtocol (
1838 &gEfiAuthenticationInfoProtocolGuid
,
1840 (VOID
**)&AuthenticationInfo
1842 if (Status
== EFI_NOT_FOUND
) {
1843 Status
= gBS
->InstallProtocolInterface (
1845 &gEfiAuthenticationInfoProtocolGuid
,
1846 EFI_NATIVE_INTERFACE
,
1847 &gIScsiAuthenticationInfo
1849 if (EFI_ERROR (Status
)) {
1857 IScsiCleanAttemptVariable ();
1860 IScsiConfigFormUnload (gIScsiIp4DriverBinding
.DriverBindingHandle
);
1863 if (mPrivate
!= NULL
) {
1864 FreePool (mPrivate
);
1869 gBS
->UninstallMultipleProtocolInterfaces (
1871 &gEfiIScsiInitiatorNameProtocolGuid
,
1872 &gIScsiInitiatorName
,
1877 EfiLibUninstallDriverBindingComponentName2 (
1878 &gIScsiIp6DriverBinding
,
1879 &gIScsiComponentName
,
1880 &gIScsiComponentName2
1884 EfiLibUninstallDriverBindingComponentName2 (
1885 &gIScsiIp4DriverBinding
,
1886 &gIScsiComponentName
,
1887 &gIScsiComponentName2