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 This program and the accompanying materials
9 are licensed and made available under the terms and conditions of the BSD License
10 which accompanies this distribution. The full text of the license may be found at
11 http://opensource.org/licenses/bsd-license.php
13 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
14 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 #include "IScsiImpl.h"
20 EFI_DRIVER_BINDING_PROTOCOL gIScsiIp4DriverBinding
= {
21 IScsiIp4DriverBindingSupported
,
22 IScsiIp4DriverBindingStart
,
23 IScsiIp4DriverBindingStop
,
29 EFI_DRIVER_BINDING_PROTOCOL gIScsiIp6DriverBinding
= {
30 IScsiIp6DriverBindingSupported
,
31 IScsiIp6DriverBindingStart
,
32 IScsiIp6DriverBindingStop
,
38 EFI_GUID gIScsiV4PrivateGuid
= ISCSI_V4_PRIVATE_GUID
;
39 EFI_GUID gIScsiV6PrivateGuid
= ISCSI_V6_PRIVATE_GUID
;
40 ISCSI_PRIVATE_DATA
*mPrivate
= NULL
;
43 Tests to see if this driver supports the RemainingDevicePath.
45 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
46 parameter is ignored by device drivers, and is optional for bus
47 drivers. For bus drivers, if this parameter is not NULL, then
48 the bus driver must determine if the bus controller specified
49 by ControllerHandle and the child controller specified
50 by RemainingDevicePath are both supported by this
53 @retval EFI_SUCCESS The RemainingDevicePath is supported or NULL.
54 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
55 RemainingDevicePath is not supported by the driver specified by This.
58 IScsiIsDevicePathSupported (
59 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
62 EFI_DEVICE_PATH_PROTOCOL
*CurrentDevicePath
;
64 CurrentDevicePath
= RemainingDevicePath
;
65 if (CurrentDevicePath
!= NULL
) {
66 while (!IsDevicePathEnd (CurrentDevicePath
)) {
67 if ((CurrentDevicePath
->Type
== MESSAGING_DEVICE_PATH
) && (CurrentDevicePath
->SubType
== MSG_ISCSI_DP
)) {
71 CurrentDevicePath
= NextDevicePathNode (CurrentDevicePath
);
74 return EFI_UNSUPPORTED
;
81 Check whether an iSCSI HBA adapter already installs an AIP instance with
82 network boot policy matching the value specified in PcdIScsiAIPNetworkBootPolicy.
83 If yes, return EFI_SUCCESS.
85 @retval EFI_SUCCESS Found an AIP with matching network boot policy.
86 @retval EFI_NOT_FOUND AIP is unavailable or the network boot policy
95 EFI_HANDLE
*AipHandleBuffer
;
97 EFI_ADAPTER_INFORMATION_PROTOCOL
*Aip
;
98 EFI_EXT_SCSI_PASS_THRU_PROTOCOL
*ExtScsiPassThru
;
99 EFI_GUID
*InfoTypesBuffer
;
100 UINTN InfoTypeBufferCount
;
105 EFI_ADAPTER_INFO_NETWORK_BOOT
*NetworkBoot
;
107 UINT8 NetworkBootPolicy
;
110 // Check any AIP instances exist in system.
113 AipHandleBuffer
= NULL
;
114 Status
= gBS
->LocateHandleBuffer (
116 &gEfiAdapterInformationProtocolGuid
,
121 if (EFI_ERROR (Status
) || AipHandleCount
== 0) {
122 return EFI_NOT_FOUND
;
125 ASSERT (AipHandleBuffer
!= NULL
);
129 for (AipIndex
= 0; AipIndex
< AipHandleCount
; AipIndex
++) {
130 Status
= gBS
->HandleProtocol (
131 AipHandleBuffer
[AipIndex
],
132 &gEfiAdapterInformationProtocolGuid
,
135 ASSERT_EFI_ERROR (Status
);
136 ASSERT (Aip
!= NULL
);
138 Status
= gBS
->HandleProtocol (
139 AipHandleBuffer
[AipIndex
],
140 &gEfiExtScsiPassThruProtocolGuid
,
141 (VOID
*) &ExtScsiPassThru
143 if (EFI_ERROR (Status
) || ExtScsiPassThru
== NULL
) {
147 InfoTypesBuffer
= NULL
;
148 InfoTypeBufferCount
= 0;
149 Status
= Aip
->GetSupportedTypes (Aip
, &InfoTypesBuffer
, &InfoTypeBufferCount
);
150 if (EFI_ERROR (Status
) || InfoTypesBuffer
== NULL
) {
154 // Check whether the AIP instance has Network boot information block.
157 for (TypeIndex
= 0; TypeIndex
< InfoTypeBufferCount
; TypeIndex
++) {
158 if (CompareGuid (&InfoTypesBuffer
[TypeIndex
], &gEfiAdapterInfoNetworkBootGuid
)) {
164 FreePool (InfoTypesBuffer
);
170 // We now have network boot information block.
174 Status
= Aip
->GetInformation (Aip
, &gEfiAdapterInfoNetworkBootGuid
, &InfoBlock
, &InfoBlockSize
);
175 if (EFI_ERROR (Status
) || InfoBlock
== NULL
) {
180 // Check whether the network boot policy matches.
182 NetworkBoot
= (EFI_ADAPTER_INFO_NETWORK_BOOT
*) InfoBlock
;
183 NetworkBootPolicy
= PcdGet8 (PcdIScsiAIPNetworkBootPolicy
);
185 if (NetworkBootPolicy
== STOP_UEFI_ISCSI_IF_HBA_INSTALL_AIP
) {
186 Status
= EFI_SUCCESS
;
189 if (((NetworkBootPolicy
& STOP_UEFI_ISCSI_IF_AIP_SUPPORT_IP4
) != 0 &&
190 !NetworkBoot
->iScsiIpv4BootCapablity
) ||
191 ((NetworkBootPolicy
& STOP_UEFI_ISCSI_IF_AIP_SUPPORT_IP6
) != 0 &&
192 !NetworkBoot
->iScsiIpv6BootCapablity
) ||
193 ((NetworkBootPolicy
& STOP_UEFI_ISCSI_IF_AIP_SUPPORT_OFFLOAD
) != 0 &&
194 !NetworkBoot
->OffloadCapability
) ||
195 ((NetworkBootPolicy
& STOP_UEFI_ISCSI_IF_AIP_SUPPORT_MPIO
) != 0 &&
196 !NetworkBoot
->iScsiMpioCapability
) ||
197 ((NetworkBootPolicy
& STOP_UEFI_ISCSI_IF_AIP_CONFIGURED_IP4
) != 0 &&
198 !NetworkBoot
->iScsiIpv4Boot
) ||
199 ((NetworkBootPolicy
& STOP_UEFI_ISCSI_IF_AIP_CONFIGURED_IP6
) != 0 &&
200 !NetworkBoot
->iScsiIpv6Boot
)) {
201 FreePool (InfoBlock
);
205 Status
= EFI_SUCCESS
;
209 Status
= EFI_NOT_FOUND
;
212 if (InfoBlock
!= NULL
) {
213 FreePool (InfoBlock
);
215 if (AipHandleBuffer
!= NULL
) {
216 FreePool (AipHandleBuffer
);
222 Tests to see if this driver supports a given controller. This is the worker function for
223 IScsiIp4(6)DriverBindingSupported.
225 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
226 @param[in] ControllerHandle The handle of the controller to test. This handle
227 must support a protocol interface that supplies
228 an I/O abstraction to the driver.
229 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
230 parameter is ignored by device drivers, and is optional for bus
231 drivers. For bus drivers, if this parameter is not NULL, then
232 the bus driver must determine if the bus controller specified
233 by ControllerHandle and the child controller specified
234 by RemainingDevicePath are both supported by this
236 @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6.
238 @retval EFI_SUCCESS The device specified by ControllerHandle and
239 RemainingDevicePath is supported by the driver specified by This.
240 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
241 RemainingDevicePath is already being managed by the driver
243 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
244 RemainingDevicePath is not supported by the driver specified by This.
249 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
250 IN EFI_HANDLE ControllerHandle
,
251 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
,
256 EFI_GUID
*IScsiServiceBindingGuid
;
257 EFI_GUID
*TcpServiceBindingGuid
;
258 EFI_GUID
*DhcpServiceBindingGuid
;
259 EFI_GUID
*DnsServiceBindingGuid
;
261 if (IpVersion
== IP_VERSION_4
) {
262 IScsiServiceBindingGuid
= &gIScsiV4PrivateGuid
;
263 TcpServiceBindingGuid
= &gEfiTcp4ServiceBindingProtocolGuid
;
264 DhcpServiceBindingGuid
= &gEfiDhcp4ServiceBindingProtocolGuid
;
265 DnsServiceBindingGuid
= &gEfiDns4ServiceBindingProtocolGuid
;
268 IScsiServiceBindingGuid
= &gIScsiV6PrivateGuid
;
269 TcpServiceBindingGuid
= &gEfiTcp6ServiceBindingProtocolGuid
;
270 DhcpServiceBindingGuid
= &gEfiDhcp6ServiceBindingProtocolGuid
;
271 DnsServiceBindingGuid
= &gEfiDns6ServiceBindingProtocolGuid
;
274 Status
= gBS
->OpenProtocol (
276 IScsiServiceBindingGuid
,
278 This
->DriverBindingHandle
,
280 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
282 if (!EFI_ERROR (Status
)) {
283 return EFI_ALREADY_STARTED
;
286 Status
= gBS
->OpenProtocol (
288 TcpServiceBindingGuid
,
290 This
->DriverBindingHandle
,
292 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
294 if (EFI_ERROR (Status
)) {
295 return EFI_UNSUPPORTED
;
298 Status
= IScsiIsDevicePathSupported (RemainingDevicePath
);
299 if (EFI_ERROR (Status
)) {
300 return EFI_UNSUPPORTED
;
303 if (IScsiDhcpIsConfigured (ControllerHandle
, IpVersion
)) {
304 Status
= gBS
->OpenProtocol (
306 DhcpServiceBindingGuid
,
308 This
->DriverBindingHandle
,
310 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
312 if (EFI_ERROR (Status
)) {
313 return EFI_UNSUPPORTED
;
317 if (IScsiDnsIsConfigured (ControllerHandle
)) {
318 Status
= gBS
->OpenProtocol (
320 DnsServiceBindingGuid
,
322 This
->DriverBindingHandle
,
324 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
326 if (EFI_ERROR (Status
)) {
327 return EFI_UNSUPPORTED
;
336 Start to manage the controller. This is the worker function for
337 IScsiIp4(6)DriverBindingStart.
339 @param[in] Image Handle of the image.
340 @param[in] ControllerHandle Handle of the controller.
341 @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6.
343 @retval EFI_SUCCES This driver was started.
344 @retval EFI_ALREADY_STARTED This driver is already running on this device.
345 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
346 @retval EFI_NOT_FOUND There is no sufficient information to establish
348 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
349 @retval EFI_DEVICE_ERROR Failed to get TCP connection device path.
350 @retval EFI_ACCESS_DENIED The protocol could not be removed from the Handle
351 because its interfaces are being used.
357 IN EFI_HANDLE ControllerHandle
,
362 ISCSI_DRIVER_DATA
*Private
;
364 LIST_ENTRY
*NextEntry
;
365 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
366 ISCSI_SESSION
*Session
;
368 EFI_EXT_SCSI_PASS_THRU_PROTOCOL
*ExistIScsiExtScsiPassThru
;
369 ISCSI_DRIVER_DATA
*ExistPrivate
;
370 UINT8
*AttemptConfigOrder
;
371 UINTN AttemptConfigOrderSize
;
373 EFI_HANDLE
*HandleBuffer
;
374 UINTN NumberOfHandles
;
375 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
376 EFI_GUID
*IScsiPrivateGuid
;
377 EFI_GUID
*TcpServiceBindingGuid
;
380 EFI_GUID
*ProtocolGuid
;
381 UINT8 NetworkBootPolicy
;
382 ISCSI_SESSION_CONFIG_NVDATA
*NvData
;
385 // Test to see if iSCSI driver supports the given controller.
388 if (IpVersion
== IP_VERSION_4
) {
389 IScsiPrivateGuid
= &gIScsiV4PrivateGuid
;
390 TcpServiceBindingGuid
= &gEfiTcp4ServiceBindingProtocolGuid
;
391 ProtocolGuid
= &gEfiTcp4ProtocolGuid
;
392 } else if (IpVersion
== IP_VERSION_6
) {
393 IScsiPrivateGuid
= &gIScsiV6PrivateGuid
;
394 TcpServiceBindingGuid
= &gEfiTcp6ServiceBindingProtocolGuid
;
395 ProtocolGuid
= &gEfiTcp6ProtocolGuid
;
397 return EFI_INVALID_PARAMETER
;
400 Status
= gBS
->OpenProtocol (
406 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
408 if (!EFI_ERROR (Status
)) {
409 return EFI_ALREADY_STARTED
;
412 Status
= gBS
->OpenProtocol (
414 TcpServiceBindingGuid
,
418 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
420 if (EFI_ERROR (Status
)) {
421 return EFI_UNSUPPORTED
;
424 NetworkBootPolicy
= PcdGet8 (PcdIScsiAIPNetworkBootPolicy
);
425 if (NetworkBootPolicy
== ALWAYS_USE_ISCSI_HBA_AND_IGNORE_UEFI_ISCSI
) {
429 if (NetworkBootPolicy
!= ALWAYS_USE_UEFI_ISCSI_AND_IGNORE_ISCSI_HBA
) {
431 // Check existing iSCSI AIP.
433 Status
= IScsiCheckAip ();
434 if (!EFI_ERROR (Status
)) {
436 // Find iSCSI AIP with specified network boot policy. return EFI_ABORTED.
443 // Record the incoming NIC info.
445 Status
= IScsiAddNic (ControllerHandle
, Image
);
446 if (EFI_ERROR (Status
)) {
451 // Create the instance private data.
453 Private
= IScsiCreateDriverData (Image
, ControllerHandle
);
454 if (Private
== NULL
) {
455 return EFI_OUT_OF_RESOURCES
;
459 // Create a underlayer child instance, but not need to configure it. Just open ChildHandle
460 // via BY_DRIVER. That is, establishing the relationship between ControllerHandle and ChildHandle.
461 // Therefore, when DisconnectController(), especially VLAN virtual controller handle,
462 // IScsiDriverBindingStop() will be called.
464 Status
= NetLibCreateServiceChild (
467 TcpServiceBindingGuid
,
468 &Private
->ChildHandle
471 if (EFI_ERROR (Status
)) {
475 Status
= gBS
->OpenProtocol (
476 Private
->ChildHandle
, /// Default Tcp child
481 EFI_OPEN_PROTOCOL_BY_DRIVER
484 if (EFI_ERROR (Status
)) {
489 // Always install private protocol no matter what happens later. We need to
490 // keep the relationship between ControllerHandle and ChildHandle.
492 Status
= gBS
->InstallProtocolInterface (
495 EFI_NATIVE_INTERFACE
,
496 &Private
->IScsiIdentifier
498 if (EFI_ERROR (Status
)) {
502 if (IpVersion
== IP_VERSION_4
) {
503 mPrivate
->Ipv6Flag
= FALSE
;
505 mPrivate
->Ipv6Flag
= TRUE
;
509 // Get the current iSCSI configuration data.
511 Status
= IScsiGetConfigData (Private
);
512 if (EFI_ERROR (Status
)) {
517 // If there is already a successul attempt, check whether this attempt is the
518 // first "enabled for MPIO" attempt. If not, still try the first attempt.
519 // In single path mode, try all attempts.
522 Status
= EFI_NOT_FOUND
;
524 if (mPrivate
->OneSessionEstablished
&& mPrivate
->EnableMpio
) {
525 AttemptConfigData
= NULL
;
526 NET_LIST_FOR_EACH (Entry
, &mPrivate
->AttemptConfigs
) {
527 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
528 if (AttemptConfigData
->SessionConfigData
.Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
533 if (AttemptConfigData
== NULL
) {
537 if (AttemptConfigData
->AttemptConfigIndex
== mPrivate
->BootSelectedIndex
) {
542 // Uninstall the original ExtScsiPassThru first.
546 // Locate all ExtScsiPassThru protocol instances.
548 Status
= gBS
->LocateHandleBuffer (
550 &gEfiExtScsiPassThruProtocolGuid
,
555 if (EFI_ERROR (Status
)) {
560 // Find ExtScsiPassThru protocol instance produced by this driver.
562 ExistIScsiExtScsiPassThru
= NULL
;
563 for (Index
= 0; Index
< NumberOfHandles
&& ExistIScsiExtScsiPassThru
== NULL
; Index
++) {
564 Status
= gBS
->HandleProtocol (
566 &gEfiDevicePathProtocolGuid
,
567 (VOID
**) &DevicePath
569 if (EFI_ERROR (Status
)) {
573 while (!IsDevicePathEnd (DevicePath
)) {
574 if ((DevicePath
->Type
== MESSAGING_DEVICE_PATH
) && (DevicePath
->SubType
== MSG_MAC_ADDR_DP
)) {
576 // Get the ExtScsiPassThru protocol instance.
578 Status
= gBS
->HandleProtocol (
580 &gEfiExtScsiPassThruProtocolGuid
,
581 (VOID
**) &ExistIScsiExtScsiPassThru
583 ASSERT_EFI_ERROR (Status
);
587 DevicePath
= NextDevicePathNode (DevicePath
);
591 FreePool (HandleBuffer
);
593 if (ExistIScsiExtScsiPassThru
== NULL
) {
594 Status
= EFI_NOT_FOUND
;
598 ExistPrivate
= ISCSI_DRIVER_DATA_FROM_EXT_SCSI_PASS_THRU (ExistIScsiExtScsiPassThru
);
600 Status
= gBS
->UninstallProtocolInterface (
601 ExistPrivate
->ExtScsiPassThruHandle
,
602 &gEfiExtScsiPassThruProtocolGuid
,
603 &ExistPrivate
->IScsiExtScsiPassThru
605 if (EFI_ERROR (Status
)) {
611 // Install the Ext SCSI PASS THRU protocol.
613 Status
= gBS
->InstallProtocolInterface (
614 &Private
->ExtScsiPassThruHandle
,
615 &gEfiExtScsiPassThruProtocolGuid
,
616 EFI_NATIVE_INTERFACE
,
617 &Private
->IScsiExtScsiPassThru
619 if (EFI_ERROR (Status
)) {
625 NET_LIST_FOR_EACH_SAFE (Entry
, NextEntry
, &mPrivate
->AttemptConfigs
) {
626 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
628 // Don't process the attempt that does not associate with the current NIC or
629 // this attempt is disabled or established.
631 if (AttemptConfigData
->NicIndex
!= mPrivate
->CurrentNic
||
632 AttemptConfigData
->SessionConfigData
.Enabled
== ISCSI_DISABLED
||
633 AttemptConfigData
->ValidPath
) {
638 // In multipath mode, don't process attempts configured for single path.
639 // In default single path mode, don't process attempts configured for multipath.
641 if ((mPrivate
->EnableMpio
&&
642 AttemptConfigData
->SessionConfigData
.Enabled
!= ISCSI_ENABLED_FOR_MPIO
) ||
643 (!mPrivate
->EnableMpio
&&
644 AttemptConfigData
->SessionConfigData
.Enabled
!= ISCSI_ENABLED
)) {
649 // Don't process the attempt that fails to get the init/target information from DHCP.
651 if (AttemptConfigData
->SessionConfigData
.InitiatorInfoFromDhcp
&&
652 !AttemptConfigData
->DhcpSuccess
) {
653 if (!mPrivate
->EnableMpio
&& mPrivate
->ValidSinglePathCount
> 0) {
654 mPrivate
->ValidSinglePathCount
--;
660 // Don't process the autoconfigure path if it is already established.
662 if (AttemptConfigData
->SessionConfigData
.IpMode
== IP_MODE_AUTOCONFIG
&&
663 AttemptConfigData
->AutoConfigureSuccess
) {
668 // Don't process the attempt if its IP mode is not in the current IP version.
670 if (!mPrivate
->Ipv6Flag
) {
671 if (AttemptConfigData
->SessionConfigData
.IpMode
== IP_MODE_IP6
) {
674 if (AttemptConfigData
->SessionConfigData
.IpMode
== IP_MODE_AUTOCONFIG
&&
675 AttemptConfigData
->AutoConfigureMode
== IP_MODE_AUTOCONFIG_IP6
) {
679 if (AttemptConfigData
->SessionConfigData
.IpMode
== IP_MODE_IP4
) {
682 if (AttemptConfigData
->SessionConfigData
.IpMode
== IP_MODE_AUTOCONFIG
&&
683 AttemptConfigData
->AutoConfigureMode
== IP_MODE_AUTOCONFIG_IP4
) {
689 // Fill in the Session and init it.
691 Session
= (ISCSI_SESSION
*) AllocateZeroPool (sizeof (ISCSI_SESSION
));
692 if (Session
== NULL
) {
693 Status
= EFI_OUT_OF_RESOURCES
;
697 Session
->Private
= Private
;
698 Session
->ConfigData
= AttemptConfigData
;
699 Session
->AuthType
= AttemptConfigData
->AuthenticationType
;
702 mPrivate
->PortString
,
703 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
705 (UINTN
) AttemptConfigData
->AttemptConfigIndex
708 if (Session
->AuthType
== ISCSI_AUTH_TYPE_CHAP
) {
709 Session
->AuthData
.CHAP
.AuthConfig
= &AttemptConfigData
->AuthConfigData
.CHAP
;
712 IScsiSessionInit (Session
, FALSE
);
715 // Try to login and create an iSCSI session according to the configuration.
717 Status
= IScsiSessionLogin (Session
);
718 if (Status
== EFI_MEDIA_CHANGED
) {
720 // The specified target is not available, and the redirection information is
721 // received. Login the session again with the updated target address.
723 Status
= IScsiSessionLogin (Session
);
724 } else if (Status
== EFI_NOT_READY
) {
725 Status
= IScsiSessionReLogin (Session
);
729 // Restore the origial user setting which specifies the proxy/virtual iSCSI target to NV region.
731 NvData
= &AttemptConfigData
->SessionConfigData
;
732 if (NvData
->RedirectFlag
) {
733 NvData
->TargetPort
= NvData
->OriginalTargetPort
;
734 CopyMem (&NvData
->TargetIp
, &NvData
->OriginalTargetIp
, sizeof (EFI_IP_ADDRESS
));
735 NvData
->RedirectFlag
= FALSE
;
738 mPrivate
->PortString
,
739 &gEfiIScsiInitiatorNameProtocolGuid
,
740 ISCSI_CONFIG_VAR_ATTR
,
741 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA
),
746 if (EFI_ERROR (Status
)) {
748 // In Single path mode, only the successful attempt will be recorded in iBFT;
749 // in multi-path mode, all the attempt entries in MPIO will be recorded in iBFT.
751 if (!mPrivate
->EnableMpio
&& mPrivate
->ValidSinglePathCount
> 0) {
752 mPrivate
->ValidSinglePathCount
--;
758 AttemptConfigData
->ValidPath
= TRUE
;
761 // Do not record the attempt in iBFT if it login with KRB5.
762 // TODO: record KRB5 attempt information in the iSCSI device path.
764 if (Session
->AuthType
== ISCSI_AUTH_TYPE_KRB
) {
765 if (!mPrivate
->EnableMpio
&& mPrivate
->ValidSinglePathCount
> 0) {
766 mPrivate
->ValidSinglePathCount
--;
769 AttemptConfigData
->ValidiBFTPath
= FALSE
;
771 AttemptConfigData
->ValidiBFTPath
= TRUE
;
775 // IScsi session success. Update the attempt state to NVR.
777 if (AttemptConfigData
->SessionConfigData
.IpMode
== IP_MODE_AUTOCONFIG
) {
778 AttemptConfigData
->AutoConfigureSuccess
= TRUE
;
782 mPrivate
->PortString
,
783 &gEfiIScsiInitiatorNameProtocolGuid
,
784 ISCSI_CONFIG_VAR_ATTR
,
785 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA
),
790 // Select the first login session. Abort others.
792 if (Private
->Session
== NULL
) {
793 Private
->Session
= Session
;
794 BootSelected
= AttemptConfigData
->AttemptConfigIndex
;
796 // Don't validate other attempt in multipath mode if one is success.
798 if (mPrivate
->EnableMpio
) {
802 IScsiSessionAbort (Session
);
809 // All attempts configured for this driver instance are not valid.
811 if (Private
->Session
== NULL
) {
812 Status
= gBS
->UninstallProtocolInterface (
813 Private
->ExtScsiPassThruHandle
,
814 &gEfiExtScsiPassThruProtocolGuid
,
815 &Private
->IScsiExtScsiPassThru
817 ASSERT_EFI_ERROR (Status
);
818 Private
->ExtScsiPassThruHandle
= NULL
;
821 // Reinstall the original ExtScsiPassThru back.
823 if (mPrivate
->OneSessionEstablished
&& ExistPrivate
!= NULL
) {
824 Status
= gBS
->InstallProtocolInterface (
825 &ExistPrivate
->ExtScsiPassThruHandle
,
826 &gEfiExtScsiPassThruProtocolGuid
,
827 EFI_NATIVE_INTERFACE
,
828 &ExistPrivate
->IScsiExtScsiPassThru
830 if (EFI_ERROR (Status
)) {
837 Status
= EFI_NOT_FOUND
;
844 // More than one attempt successes.
846 if (Private
->Session
!= NULL
&& mPrivate
->OneSessionEstablished
) {
848 AttemptConfigOrder
= IScsiGetVariableAndSize (
851 &AttemptConfigOrderSize
853 if (AttemptConfigOrder
== NULL
) {
856 for (Index
= 0; Index
< AttemptConfigOrderSize
/ sizeof (UINT8
); Index
++) {
857 if (AttemptConfigOrder
[Index
] == mPrivate
->BootSelectedIndex
||
858 AttemptConfigOrder
[Index
] == BootSelected
) {
863 if (mPrivate
->EnableMpio
) {
865 // Use the attempt in earlier order. Abort the later one in MPIO.
867 if (AttemptConfigOrder
[Index
] == mPrivate
->BootSelectedIndex
) {
868 IScsiSessionAbort (Private
->Session
);
869 FreePool (Private
->Session
);
870 Private
->Session
= NULL
;
871 gBS
->UninstallProtocolInterface (
872 Private
->ExtScsiPassThruHandle
,
873 &gEfiExtScsiPassThruProtocolGuid
,
874 &Private
->IScsiExtScsiPassThru
876 Private
->ExtScsiPassThruHandle
= NULL
;
879 // Reinstall the original ExtScsiPassThru back.
881 Status
= gBS
->InstallProtocolInterface (
882 &ExistPrivate
->ExtScsiPassThruHandle
,
883 &gEfiExtScsiPassThruProtocolGuid
,
884 EFI_NATIVE_INTERFACE
,
885 &ExistPrivate
->IScsiExtScsiPassThru
887 if (EFI_ERROR (Status
)) {
893 if (AttemptConfigOrder
[Index
] != BootSelected
) {
896 mPrivate
->BootSelectedIndex
= BootSelected
;
898 // Clear the resource in ExistPrivate.
900 gBS
->UninstallProtocolInterface (
901 ExistPrivate
->Controller
,
903 &ExistPrivate
->IScsiIdentifier
906 IScsiRemoveNic (ExistPrivate
->Controller
);
907 if (ExistPrivate
->Session
!= NULL
) {
908 IScsiSessionAbort (ExistPrivate
->Session
);
911 if (ExistPrivate
->DevicePath
!= NULL
) {
912 Status
= gBS
->UninstallProtocolInterface (
913 ExistPrivate
->ExtScsiPassThruHandle
,
914 &gEfiDevicePathProtocolGuid
,
915 ExistPrivate
->DevicePath
917 if (EFI_ERROR (Status
)) {
921 FreePool (ExistPrivate
->DevicePath
);
924 gBS
->CloseEvent (ExistPrivate
->ExitBootServiceEvent
);
925 FreePool (ExistPrivate
);
930 // Use the attempt in earlier order as boot selected in single path mode.
932 if (AttemptConfigOrder
[Index
] == mPrivate
->BootSelectedIndex
) {
940 mPrivate
->OneSessionEstablished
= TRUE
;
941 mPrivate
->BootSelectedIndex
= BootSelected
;
945 // Duplicate the Session's tcp connection device path. The source port field
946 // will be set to zero as one iSCSI session is comprised of several iSCSI
949 Private
->DevicePath
= IScsiGetTcpConnDevicePath (Private
->Session
);
950 if (Private
->DevicePath
== NULL
) {
951 Status
= EFI_DEVICE_ERROR
;
955 // Install the updated device path onto the ExtScsiPassThruHandle.
957 Status
= gBS
->InstallProtocolInterface (
958 &Private
->ExtScsiPassThruHandle
,
959 &gEfiDevicePathProtocolGuid
,
960 EFI_NATIVE_INTERFACE
,
963 if (EFI_ERROR (Status
)) {
968 // ISCSI children should share the default Tcp child, just open the default Tcp child via BY_CHILD_CONTROLLER.
970 Status
= gBS
->OpenProtocol (
971 Private
->ChildHandle
, /// Default Tcp child
975 Private
->ExtScsiPassThruHandle
,
976 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
978 if (EFI_ERROR (Status
)) {
979 gBS
->UninstallMultipleProtocolInterfaces (
980 Private
->ExtScsiPassThruHandle
,
981 &gEfiExtScsiPassThruProtocolGuid
,
982 &Private
->IScsiExtScsiPassThru
,
983 &gEfiDevicePathProtocolGuid
,
994 // Update/Publish the iSCSI Boot Firmware Table.
996 if (mPrivate
->BootSelectedIndex
!= 0) {
1004 if (Private
->Session
!= NULL
) {
1005 IScsiSessionAbort (Private
->Session
);
1012 Stops a device controller or a bus controller. This is the worker function for
1013 IScsiIp4(6)DriverBindingStop.
1015 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
1016 @param[in] ControllerHandle A handle to the device being stopped. The handle must
1017 support a bus specific I/O protocol for the driver
1018 to use to stop the device.
1019 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
1020 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
1021 if NumberOfChildren is 0.
1022 @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6.
1024 @retval EFI_SUCCESS The device was stopped.
1025 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
1026 @retval EFI_INVALID_PARAMETER Child handle is NULL.
1027 @retval EFI_ACCESS_DENIED The protocol could not be removed from the Handle
1028 because its interfaces are being used.
1034 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1035 IN EFI_HANDLE ControllerHandle
,
1036 IN UINTN NumberOfChildren
,
1037 IN EFI_HANDLE
*ChildHandleBuffer OPTIONAL
,
1041 EFI_HANDLE IScsiController
;
1043 ISCSI_PRIVATE_PROTOCOL
*IScsiIdentifier
;
1044 ISCSI_DRIVER_DATA
*Private
;
1045 EFI_EXT_SCSI_PASS_THRU_PROTOCOL
*PassThru
;
1046 ISCSI_CONNECTION
*Conn
;
1047 EFI_GUID
*ProtocolGuid
;
1048 EFI_GUID
*TcpServiceBindingGuid
;
1049 EFI_GUID
*TcpProtocolGuid
;
1052 if (NumberOfChildren
!= 0) {
1054 // We should have only one child.
1056 Status
= gBS
->OpenProtocol (
1057 ChildHandleBuffer
[0],
1058 &gEfiExtScsiPassThruProtocolGuid
,
1059 (VOID
**) &PassThru
,
1060 This
->DriverBindingHandle
,
1062 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1064 if (EFI_ERROR (Status
)) {
1065 return EFI_DEVICE_ERROR
;
1068 Private
= ISCSI_DRIVER_DATA_FROM_EXT_SCSI_PASS_THRU (PassThru
);
1069 Conn
= NET_LIST_HEAD (&Private
->Session
->Conns
, ISCSI_CONNECTION
, Link
);
1072 // Previously the TCP protocol is opened BY_CHILD_CONTROLLER. Just close
1073 // the protocol here, but do not uninstall the device path protocol and
1074 // EXT SCSI PASS THRU protocol installed on ExtScsiPassThruHandle.
1076 if (IpVersion
== IP_VERSION_4
) {
1077 ProtocolGuid
= &gEfiTcp4ProtocolGuid
;
1079 ProtocolGuid
= &gEfiTcp6ProtocolGuid
;
1082 gBS
->CloseProtocol (
1083 Private
->ChildHandle
,
1086 Private
->ExtScsiPassThruHandle
1089 gBS
->CloseProtocol (
1093 Private
->ExtScsiPassThruHandle
1100 // Get the handle of the controller we are controling.
1102 if (IpVersion
== IP_VERSION_4
) {
1103 ProtocolGuid
= &gIScsiV4PrivateGuid
;
1104 TcpProtocolGuid
= &gEfiTcp4ProtocolGuid
;
1105 TcpServiceBindingGuid
= &gEfiTcp4ServiceBindingProtocolGuid
;
1107 ProtocolGuid
= &gIScsiV6PrivateGuid
;
1108 TcpProtocolGuid
= &gEfiTcp6ProtocolGuid
;
1109 TcpServiceBindingGuid
= &gEfiTcp6ServiceBindingProtocolGuid
;
1111 IScsiController
= NetLibGetNicHandle (ControllerHandle
, TcpProtocolGuid
);
1112 if (IScsiController
== NULL
) {
1116 Status
= gBS
->OpenProtocol (
1119 (VOID
**) &IScsiIdentifier
,
1120 This
->DriverBindingHandle
,
1122 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1124 if (EFI_ERROR (Status
)) {
1125 return EFI_DEVICE_ERROR
;
1128 Private
= ISCSI_DRIVER_DATA_FROM_IDENTIFIER (IScsiIdentifier
);
1129 ASSERT (Private
!= NULL
);
1131 if (Private
->ChildHandle
!= NULL
) {
1132 Status
= gBS
->CloseProtocol (
1133 Private
->ChildHandle
,
1135 This
->DriverBindingHandle
,
1139 ASSERT (!EFI_ERROR (Status
));
1141 Status
= NetLibDestroyServiceChild (
1143 This
->DriverBindingHandle
,
1144 TcpServiceBindingGuid
,
1145 Private
->ChildHandle
1148 ASSERT (!EFI_ERROR (Status
));
1151 gBS
->UninstallProtocolInterface (
1154 &Private
->IScsiIdentifier
1160 IScsiRemoveNic (IScsiController
);
1163 // Update the iSCSI Boot Firware Table.
1165 IScsiPublishIbft ();
1167 if (Private
->Session
!= NULL
) {
1168 IScsiSessionAbort (Private
->Session
);
1171 Status
= IScsiCleanDriverData (Private
);
1173 if (EFI_ERROR (Status
)) {
1181 Tests to see if this driver supports a given controller. If a child device is provided,
1182 it tests to see if this driver supports creating a handle for the specified child device.
1184 This function checks to see if the driver specified by This supports the device specified by
1185 ControllerHandle. Drivers typically use the device path attached to
1186 ControllerHandle and/or the services from the bus I/O abstraction attached to
1187 ControllerHandle to determine if the driver supports ControllerHandle. This function
1188 may be called many times during platform initialization. In order to reduce boot times, the tests
1189 performed by this function must be very small and take as little time as possible to execute. This
1190 function must not change the state of any hardware devices, and this function must be aware that the
1191 device specified by ControllerHandle may already be managed by the same driver or a
1192 different driver. This function must match its calls to AllocatePages() with FreePages(),
1193 AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
1194 Since ControllerHandle may have been previously started by the same driver, if a protocol is
1195 already in the opened state, then it must not be closed with CloseProtocol(). This is required
1196 to guarantee the state of ControllerHandle is not modified by this function.
1198 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
1199 @param[in] ControllerHandle The handle of the controller to test. This handle
1200 must support a protocol interface that supplies
1201 an I/O abstraction to the driver.
1202 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
1203 parameter is ignored by device drivers, and is optional for bus
1204 drivers. For bus drivers, if this parameter is not NULL, then
1205 the bus driver must determine if the bus controller specified
1206 by ControllerHandle and the child controller specified
1207 by RemainingDevicePath are both supported by this
1210 @retval EFI_SUCCESS The device specified by ControllerHandle and
1211 RemainingDevicePath is supported by the driver specified by This.
1212 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
1213 RemainingDevicePath is already managed by the driver
1215 @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
1216 RemainingDevicePath is already managed by a different
1217 driver or an application that requires exclusive access.
1218 Currently not implemented.
1219 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
1220 RemainingDevicePath is not supported by the driver specified by This.
1224 IScsiIp4DriverBindingSupported (
1225 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1226 IN EFI_HANDLE ControllerHandle
,
1227 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
1230 return IScsiSupported (
1233 RemainingDevicePath
,
1239 Starts a device controller or a bus controller.
1241 The Start() function is designed to be invoked from the EFI boot service ConnectController().
1242 As a result, much of the error checking on the parameters to Start() has been moved into this
1243 common boot service. It is legal to call Start() from other locations,
1244 but the following calling restrictions must be followed or the system behavior will not be deterministic.
1245 1. ControllerHandle must be a valid EFI_HANDLE.
1246 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
1247 EFI_DEVICE_PATH_PROTOCOL.
1248 3. Prior to calling Start(), the Supported() function for the driver specified by This must
1249 have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
1251 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
1252 @param[in] ControllerHandle The handle of the controller to start. This handle
1253 must support a protocol interface that supplies
1254 an I/O abstraction to the driver.
1255 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
1256 parameter is ignored by device drivers, and is optional for bus
1257 drivers. For a bus driver, if this parameter is NULL, then handles
1258 for all the children of Controller are created by this driver.
1259 If this parameter is not NULL and the first Device Path Node is
1260 not the End of Device Path Node, then only the handle for the
1261 child device specified by the first Device Path Node of
1262 RemainingDevicePath is created by this driver.
1263 If the first Device Path Node of RemainingDevicePath is
1264 the End of Device Path Node, no child handle is created by this
1267 @retval EFI_SUCCESS The device was started.
1268 @retval EFI_DEVICE_ERROR The device could not be started due to a device error. Currently not implemented.
1269 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
1270 @retval Others The driver failed to start the device.
1275 IScsiIp4DriverBindingStart (
1276 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1277 IN EFI_HANDLE ControllerHandle
,
1278 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
1283 Status
= IScsiStart (This
->DriverBindingHandle
, ControllerHandle
, IP_VERSION_4
);
1284 if (Status
== EFI_ALREADY_STARTED
) {
1285 Status
= EFI_SUCCESS
;
1292 Stops a device controller or a bus controller.
1294 The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
1295 As a result, much of the error checking on the parameters to Stop() has been moved
1296 into this common boot service. It is legal to call Stop() from other locations,
1297 but the following calling restrictions must be followed or the system behavior will not be deterministic.
1298 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
1299 same driver's Start() function.
1300 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
1301 EFI_HANDLE. In addition, all of these handles must have been created in this driver's
1302 Start() function, and the Start() function must have called OpenProtocol() on
1303 ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
1305 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
1306 @param[in] ControllerHandle A handle to the device being stopped. The handle must
1307 support a bus specific I/O protocol for the driver
1308 to use to stop the device.
1309 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
1310 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
1311 if NumberOfChildren is 0.
1313 @retval EFI_SUCCESS The device was stopped.
1314 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
1319 IScsiIp4DriverBindingStop (
1320 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1321 IN EFI_HANDLE ControllerHandle
,
1322 IN UINTN NumberOfChildren
,
1323 IN EFI_HANDLE
*ChildHandleBuffer OPTIONAL
1336 Tests to see if this driver supports a given controller. If a child device is provided,
1337 it tests to see if this driver supports creating a handle for the specified child device.
1339 This function checks to see if the driver specified by This supports the device specified by
1340 ControllerHandle. Drivers typically use the device path attached to
1341 ControllerHandle and/or the services from the bus I/O abstraction attached to
1342 ControllerHandle to determine if the driver supports ControllerHandle. This function
1343 may be called many times during platform initialization. In order to reduce boot times, the tests
1344 performed by this function must be very small and take as little time as possible to execute. This
1345 function must not change the state of any hardware devices, and this function must be aware that the
1346 device specified by ControllerHandle may already be managed by the same driver or a
1347 different driver. This function must match its calls to AllocatePages() with FreePages(),
1348 AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
1349 Since ControllerHandle may have been previously started by the same driver, if a protocol is
1350 already in the opened state, then it must not be closed with CloseProtocol(). This is required
1351 to guarantee the state of ControllerHandle is not modified by this function.
1353 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
1354 @param[in] ControllerHandle The handle of the controller to test. This handle
1355 must support a protocol interface that supplies
1356 an I/O abstraction to the driver.
1357 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
1358 parameter is ignored by device drivers, and is optional for bus
1359 drivers. For bus drivers, if this parameter is not NULL, then
1360 the bus driver must determine if the bus controller specified
1361 by ControllerHandle and the child controller specified
1362 by RemainingDevicePath are both supported by this
1365 @retval EFI_SUCCESS The device specified by ControllerHandle and
1366 RemainingDevicePath is supported by the driver specified by This.
1367 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
1368 RemainingDevicePath is already managed by the driver
1370 @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
1371 RemainingDevicePath is already managed by a different
1372 driver or an application that requires exclusive access.
1373 Currently not implemented.
1374 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
1375 RemainingDevicePath is not supported by the driver specified by This.
1379 IScsiIp6DriverBindingSupported (
1380 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1381 IN EFI_HANDLE ControllerHandle
,
1382 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
1385 return IScsiSupported (
1388 RemainingDevicePath
,
1394 Starts a device controller or a bus controller.
1396 The Start() function is designed to be invoked from the EFI boot service ConnectController().
1397 As a result, much of the error checking on the parameters to Start() has been moved into this
1398 common boot service. It is legal to call Start() from other locations,
1399 but the following calling restrictions must be followed or the system behavior will not be deterministic.
1400 1. ControllerHandle must be a valid EFI_HANDLE.
1401 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
1402 EFI_DEVICE_PATH_PROTOCOL.
1403 3. Prior to calling Start(), the Supported() function for the driver specified by This must
1404 have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
1406 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
1407 @param[in] ControllerHandle The handle of the controller to start. This handle
1408 must support a protocol interface that supplies
1409 an I/O abstraction to the driver.
1410 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
1411 parameter is ignored by device drivers, and is optional for bus
1412 drivers. For a bus driver, if this parameter is NULL, then handles
1413 for all the children of Controller are created by this driver.
1414 If this parameter is not NULL and the first Device Path Node is
1415 not the End of Device Path Node, then only the handle for the
1416 child device specified by the first Device Path Node of
1417 RemainingDevicePath is created by this driver.
1418 If the first Device Path Node of RemainingDevicePath is
1419 the End of Device Path Node, no child handle is created by this
1422 @retval EFI_SUCCESS The device was started.
1423 @retval EFI_DEVICE_ERROR The device could not be started due to a device error. Currently not implemented.
1424 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
1425 @retval Others The driver failed to start the device.
1430 IScsiIp6DriverBindingStart (
1431 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1432 IN EFI_HANDLE ControllerHandle
,
1433 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
1438 Status
= IScsiStart (This
->DriverBindingHandle
, ControllerHandle
, IP_VERSION_6
);
1439 if (Status
== EFI_ALREADY_STARTED
) {
1440 Status
= EFI_SUCCESS
;
1447 Stops a device controller or a bus controller.
1449 The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
1450 As a result, much of the error checking on the parameters to Stop() has been moved
1451 into this common boot service. It is legal to call Stop() from other locations,
1452 but the following calling restrictions must be followed or the system behavior will not be deterministic.
1453 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
1454 same driver's Start() function.
1455 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
1456 EFI_HANDLE. In addition, all of these handles must have been created in this driver's
1457 Start() function, and the Start() function must have called OpenProtocol() on
1458 ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
1460 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
1461 @param[in] ControllerHandle A handle to the device being stopped. The handle must
1462 support a bus specific I/O protocol for the driver
1463 to use to stop the device.
1464 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
1465 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
1466 if NumberOfChildren is 0.
1468 @retval EFI_SUCCESS The device was stopped.
1469 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
1474 IScsiIp6DriverBindingStop (
1475 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1476 IN EFI_HANDLE ControllerHandle
,
1477 IN UINTN NumberOfChildren
,
1478 IN EFI_HANDLE
*ChildHandleBuffer OPTIONAL
1491 Unload the iSCSI driver.
1493 @param[in] ImageHandle The handle of the driver image.
1495 @retval EFI_SUCCESS The driver is unloaded.
1496 @retval EFI_DEVICE_ERROR An unexpected error occurred.
1502 IN EFI_HANDLE ImageHandle
1506 UINTN DeviceHandleCount
;
1507 EFI_HANDLE
*DeviceHandleBuffer
;
1509 EFI_COMPONENT_NAME_PROTOCOL
*ComponentName
;
1510 EFI_COMPONENT_NAME2_PROTOCOL
*ComponentName2
;
1513 // Try to disonnect the driver from the devices it's controlling.
1515 Status
= gBS
->LocateHandleBuffer (
1522 if (EFI_ERROR (Status
)) {
1527 // Disconnect the iSCSI4 driver from the controlled device.
1529 for (Index
= 0; Index
< DeviceHandleCount
; Index
++) {
1530 Status
= IScsiTestManagedDevice (
1531 DeviceHandleBuffer
[Index
],
1532 gIScsiIp4DriverBinding
.DriverBindingHandle
,
1533 &gEfiTcp4ProtocolGuid
)
1535 if (EFI_ERROR (Status
)) {
1538 Status
= gBS
->DisconnectController (
1539 DeviceHandleBuffer
[Index
],
1540 gIScsiIp4DriverBinding
.DriverBindingHandle
,
1543 if (EFI_ERROR (Status
)) {
1549 // Disconnect the iSCSI6 driver from the controlled device.
1551 for (Index
= 0; Index
< DeviceHandleCount
; Index
++) {
1552 Status
= IScsiTestManagedDevice (
1553 DeviceHandleBuffer
[Index
],
1554 gIScsiIp6DriverBinding
.DriverBindingHandle
,
1555 &gEfiTcp6ProtocolGuid
1557 if (EFI_ERROR (Status
)) {
1560 Status
= gBS
->DisconnectController (
1561 DeviceHandleBuffer
[Index
],
1562 gIScsiIp6DriverBinding
.DriverBindingHandle
,
1565 if (EFI_ERROR (Status
)) {
1571 // Unload the iSCSI configuration form.
1573 Status
= IScsiConfigFormUnload (gIScsiIp4DriverBinding
.DriverBindingHandle
);
1574 if (EFI_ERROR (Status
)) {
1579 // Uninstall the protocols installed by iSCSI driver.
1581 Status
= gBS
->UninstallMultipleProtocolInterfaces (
1583 &gEfiAuthenticationInfoProtocolGuid
,
1584 &gIScsiAuthenticationInfo
,
1587 if (EFI_ERROR (Status
)) {
1591 if (gIScsiControllerNameTable
!= NULL
) {
1592 Status
= FreeUnicodeStringTable (gIScsiControllerNameTable
);
1593 if (EFI_ERROR (Status
)) {
1596 gIScsiControllerNameTable
= NULL
;
1600 // Uninstall the ComponentName and ComponentName2 protocol from iSCSI4 driver binding handle
1601 // if it has been installed.
1603 Status
= gBS
->HandleProtocol (
1604 gIScsiIp4DriverBinding
.DriverBindingHandle
,
1605 &gEfiComponentNameProtocolGuid
,
1606 (VOID
**) &ComponentName
1608 if (!EFI_ERROR (Status
)) {
1609 Status
= gBS
->UninstallMultipleProtocolInterfaces (
1610 gIScsiIp4DriverBinding
.DriverBindingHandle
,
1611 &gEfiComponentNameProtocolGuid
,
1615 if (EFI_ERROR (Status
)) {
1620 Status
= gBS
->HandleProtocol (
1621 gIScsiIp4DriverBinding
.DriverBindingHandle
,
1622 &gEfiComponentName2ProtocolGuid
,
1623 (VOID
**) &ComponentName2
1625 if (!EFI_ERROR (Status
)) {
1626 gBS
->UninstallMultipleProtocolInterfaces (
1627 gIScsiIp4DriverBinding
.DriverBindingHandle
,
1628 &gEfiComponentName2ProtocolGuid
,
1632 if (EFI_ERROR (Status
)) {
1638 // Uninstall the ComponentName and ComponentName2 protocol from iSCSI6 driver binding handle
1639 // if it has been installed.
1641 Status
= gBS
->HandleProtocol (
1642 gIScsiIp6DriverBinding
.DriverBindingHandle
,
1643 &gEfiComponentNameProtocolGuid
,
1644 (VOID
**) &ComponentName
1646 if (!EFI_ERROR (Status
)) {
1647 Status
= gBS
->UninstallMultipleProtocolInterfaces (
1648 gIScsiIp6DriverBinding
.DriverBindingHandle
,
1649 &gEfiComponentNameProtocolGuid
,
1653 if (EFI_ERROR (Status
)) {
1658 Status
= gBS
->HandleProtocol (
1659 gIScsiIp6DriverBinding
.DriverBindingHandle
,
1660 &gEfiComponentName2ProtocolGuid
,
1661 (VOID
**) &ComponentName2
1663 if (!EFI_ERROR (Status
)) {
1664 gBS
->UninstallMultipleProtocolInterfaces (
1665 gIScsiIp6DriverBinding
.DriverBindingHandle
,
1666 &gEfiComponentName2ProtocolGuid
,
1670 if (EFI_ERROR (Status
)) {
1676 // Uninstall the IScsiInitiatorNameProtocol and all the driver binding protocols.
1678 Status
= gBS
->UninstallMultipleProtocolInterfaces (
1679 gIScsiIp4DriverBinding
.DriverBindingHandle
,
1680 &gEfiDriverBindingProtocolGuid
,
1681 &gIScsiIp4DriverBinding
,
1682 &gEfiIScsiInitiatorNameProtocolGuid
,
1683 &gIScsiInitiatorName
,
1686 if (EFI_ERROR (Status
)) {
1690 Status
= gBS
->UninstallMultipleProtocolInterfaces (
1691 gIScsiIp6DriverBinding
.DriverBindingHandle
,
1692 &gEfiDriverBindingProtocolGuid
,
1693 &gIScsiIp6DriverBinding
,
1699 if (DeviceHandleBuffer
!= NULL
) {
1700 FreePool (DeviceHandleBuffer
);
1707 This is the declaration of an EFI image entry point. This entry point is
1708 the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including
1709 both device drivers and bus drivers.
1711 The entry point for iSCSI driver which initializes the global variables and
1712 installs the driver binding, component name protocol, iSCSI initiator name
1713 protocol and Authentication Info protocol on its image.
1715 @param[in] ImageHandle The firmware allocated handle for the UEFI image.
1716 @param[in] SystemTable A pointer to the EFI System Table.
1718 @retval EFI_SUCCESS The operation completed successfully.
1719 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
1724 IScsiDriverEntryPoint (
1725 IN EFI_HANDLE ImageHandle
,
1726 IN EFI_SYSTEM_TABLE
*SystemTable
1730 EFI_ISCSI_INITIATOR_NAME_PROTOCOL
*IScsiInitiatorName
;
1731 EFI_AUTHENTICATION_INFO_PROTOCOL
*AuthenticationInfo
;
1734 // There should be only one EFI_ISCSI_INITIATOR_NAME_PROTOCOL.
1736 Status
= gBS
->LocateProtocol (
1737 &gEfiIScsiInitiatorNameProtocolGuid
,
1739 (VOID
**) &IScsiInitiatorName
1741 if (!EFI_ERROR (Status
)) {
1742 return EFI_ACCESS_DENIED
;
1746 // Initialize the EFI Driver Library.
1748 Status
= EfiLibInstallDriverBindingComponentName2 (
1751 &gIScsiIp4DriverBinding
,
1753 &gIScsiComponentName
,
1754 &gIScsiComponentName2
1756 if (EFI_ERROR (Status
)) {
1760 Status
= EfiLibInstallDriverBindingComponentName2 (
1763 &gIScsiIp6DriverBinding
,
1765 &gIScsiComponentName
,
1766 &gIScsiComponentName2
1768 if (EFI_ERROR (Status
)) {
1773 // Install the iSCSI Initiator Name Protocol.
1775 Status
= gBS
->InstallProtocolInterface (
1777 &gEfiIScsiInitiatorNameProtocolGuid
,
1778 EFI_NATIVE_INTERFACE
,
1779 &gIScsiInitiatorName
1781 if (EFI_ERROR (Status
)) {
1786 // Create the private data structures.
1788 mPrivate
= AllocateZeroPool (sizeof (ISCSI_PRIVATE_DATA
));
1789 if (mPrivate
== NULL
) {
1790 Status
= EFI_OUT_OF_RESOURCES
;
1794 InitializeListHead (&mPrivate
->NicInfoList
);
1795 InitializeListHead (&mPrivate
->AttemptConfigs
);
1798 // Initialize the configuration form of iSCSI.
1800 Status
= IScsiConfigFormInit (gIScsiIp4DriverBinding
.DriverBindingHandle
);
1801 if (EFI_ERROR (Status
)) {
1806 // Create the Maximum Attempts.
1808 Status
= IScsiCreateAttempts (PcdGet8 (PcdMaxIScsiAttemptNumber
));
1809 if (EFI_ERROR (Status
)) {
1814 // Create Keywords for all the Attempts.
1816 Status
= IScsiCreateKeywords (PcdGet8 (PcdMaxIScsiAttemptNumber
));
1817 if (EFI_ERROR (Status
)) {
1822 // There should be only one EFI_AUTHENTICATION_INFO_PROTOCOL. If already exists,
1823 // do not produce the protocol instance.
1825 Status
= gBS
->LocateProtocol (
1826 &gEfiAuthenticationInfoProtocolGuid
,
1828 (VOID
**) &AuthenticationInfo
1830 if (Status
== EFI_NOT_FOUND
) {
1831 Status
= gBS
->InstallProtocolInterface (
1833 &gEfiAuthenticationInfoProtocolGuid
,
1834 EFI_NATIVE_INTERFACE
,
1835 &gIScsiAuthenticationInfo
1837 if (EFI_ERROR (Status
)) {
1845 IScsiCleanAttemptVariable ();
1848 IScsiConfigFormUnload (gIScsiIp4DriverBinding
.DriverBindingHandle
);
1851 if (mPrivate
!= NULL
) {
1852 FreePool (mPrivate
);
1857 gBS
->UninstallMultipleProtocolInterfaces (
1859 &gEfiIScsiInitiatorNameProtocolGuid
,
1860 &gIScsiInitiatorName
,
1865 EfiLibUninstallDriverBindingComponentName2 (
1866 &gIScsiIp6DriverBinding
,
1867 &gIScsiComponentName
,
1868 &gIScsiComponentName2
1872 EfiLibUninstallDriverBindingComponentName2 (
1873 &gIScsiIp4DriverBinding
,
1874 &gIScsiComponentName
,
1875 &gIScsiComponentName2