]> git.proxmox.com Git - mirror_edk2.git/blame - NetworkPkg/IScsiDxe/IScsiDriver.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / NetworkPkg / IScsiDxe / IScsiDriver.c
CommitLineData
4c5a5e0c 1/** @file\r
2 The entry point of IScsi driver.\r
3\r
15666b8c 4Copyright (c) 2019, NVIDIA Corporation. All rights reserved.\r
f75a7f56 5Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>\r
483ee515 6(C) Copyright 2017 Hewlett Packard Enterprise Development LP<BR>\r
7\r
ecf98fbc 8SPDX-License-Identifier: BSD-2-Clause-Patent\r
4c5a5e0c 9\r
10**/\r
11\r
12#include "IScsiImpl.h"\r
13\r
d1050b9d 14EFI_DRIVER_BINDING_PROTOCOL gIScsiIp4DriverBinding = {\r
6879581d 15 IScsiIp4DriverBindingSupported,\r
16 IScsiIp4DriverBindingStart,\r
17 IScsiIp4DriverBindingStop,\r
18 0xa,\r
19 NULL,\r
20 NULL\r
21};\r
22\r
d1050b9d 23EFI_DRIVER_BINDING_PROTOCOL gIScsiIp6DriverBinding = {\r
6879581d 24 IScsiIp6DriverBindingSupported,\r
25 IScsiIp6DriverBindingStart,\r
26 IScsiIp6DriverBindingStop,\r
4c5a5e0c 27 0xa,\r
28 NULL,\r
29 NULL\r
30};\r
31\r
d1050b9d
MK
32EFI_GUID gIScsiV4PrivateGuid = ISCSI_V4_PRIVATE_GUID;\r
33EFI_GUID gIScsiV6PrivateGuid = ISCSI_V6_PRIVATE_GUID;\r
34ISCSI_PRIVATE_DATA *mPrivate = NULL;\r
4c5a5e0c 35\r
36/**\r
f75a7f56
LG
37 Tests to see if this driver supports the RemainingDevicePath.\r
38\r
39 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This\r
40 parameter is ignored by device drivers, and is optional for bus\r
41 drivers. For bus drivers, if this parameter is not NULL, then\r
42 the bus driver must determine if the bus controller specified\r
43 by ControllerHandle and the child controller specified\r
44 by RemainingDevicePath are both supported by this\r
4c5a5e0c 45 bus driver.\r
46\r
47 @retval EFI_SUCCESS The RemainingDevicePath is supported or NULL.\r
48 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and\r
49 RemainingDevicePath is not supported by the driver specified by This.\r
50**/\r
51EFI_STATUS\r
52IScsiIsDevicePathSupported (\r
d1050b9d 53 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
4c5a5e0c 54 )\r
55{\r
56 EFI_DEVICE_PATH_PROTOCOL *CurrentDevicePath;\r
57\r
58 CurrentDevicePath = RemainingDevicePath;\r
59 if (CurrentDevicePath != NULL) {\r
60 while (!IsDevicePathEnd (CurrentDevicePath)) {\r
61 if ((CurrentDevicePath->Type == MESSAGING_DEVICE_PATH) && (CurrentDevicePath->SubType == MSG_ISCSI_DP)) {\r
62 return EFI_SUCCESS;\r
63 }\r
64\r
65 CurrentDevicePath = NextDevicePathNode (CurrentDevicePath);\r
66 }\r
67\r
68 return EFI_UNSUPPORTED;\r
69 }\r
70\r
71 return EFI_SUCCESS;\r
72}\r
73\r
8873b174
YT
74/**\r
75 Check whether an iSCSI HBA adapter already installs an AIP instance with\r
76 network boot policy matching the value specified in PcdIScsiAIPNetworkBootPolicy.\r
77 If yes, return EFI_SUCCESS.\r
78\r
79 @retval EFI_SUCCESS Found an AIP with matching network boot policy.\r
80 @retval EFI_NOT_FOUND AIP is unavailable or the network boot policy\r
81 not matched.\r
82**/\r
83EFI_STATUS\r
84IScsiCheckAip (\r
63393404 85 VOID\r
8873b174
YT
86 )\r
87{\r
d1050b9d
MK
88 UINTN AipHandleCount;\r
89 EFI_HANDLE *AipHandleBuffer;\r
90 UINTN AipIndex;\r
91 EFI_ADAPTER_INFORMATION_PROTOCOL *Aip;\r
92 EFI_EXT_SCSI_PASS_THRU_PROTOCOL *ExtScsiPassThru;\r
93 EFI_GUID *InfoTypesBuffer;\r
94 UINTN InfoTypeBufferCount;\r
95 UINTN TypeIndex;\r
96 VOID *InfoBlock;\r
97 UINTN InfoBlockSize;\r
98 BOOLEAN Supported;\r
99 EFI_ADAPTER_INFO_NETWORK_BOOT *NetworkBoot;\r
100 EFI_STATUS Status;\r
101 UINT8 NetworkBootPolicy;\r
8873b174
YT
102\r
103 //\r
104 // Check any AIP instances exist in system.\r
105 //\r
5346adbb
JW
106 AipHandleCount = 0;\r
107 AipHandleBuffer = NULL;\r
d1050b9d
MK
108 Status = gBS->LocateHandleBuffer (\r
109 ByProtocol,\r
110 &gEfiAdapterInformationProtocolGuid,\r
111 NULL,\r
112 &AipHandleCount,\r
113 &AipHandleBuffer\r
114 );\r
115 if (EFI_ERROR (Status) || (AipHandleCount == 0)) {\r
8873b174
YT
116 return EFI_NOT_FOUND;\r
117 }\r
118\r
5346adbb
JW
119 ASSERT (AipHandleBuffer != NULL);\r
120\r
8873b174
YT
121 InfoBlock = NULL;\r
122\r
123 for (AipIndex = 0; AipIndex < AipHandleCount; AipIndex++) {\r
124 Status = gBS->HandleProtocol (\r
125 AipHandleBuffer[AipIndex],\r
126 &gEfiAdapterInformationProtocolGuid,\r
d1050b9d 127 (VOID *)&Aip\r
8873b174
YT
128 );\r
129 ASSERT_EFI_ERROR (Status);\r
130 ASSERT (Aip != NULL);\r
131\r
132 Status = gBS->HandleProtocol (\r
133 AipHandleBuffer[AipIndex],\r
134 &gEfiExtScsiPassThruProtocolGuid,\r
d1050b9d 135 (VOID *)&ExtScsiPassThru\r
8873b174 136 );\r
d1050b9d 137 if (EFI_ERROR (Status) || (ExtScsiPassThru == NULL)) {\r
8873b174
YT
138 continue;\r
139 }\r
140\r
141 InfoTypesBuffer = NULL;\r
142 InfoTypeBufferCount = 0;\r
d1050b9d
MK
143 Status = Aip->GetSupportedTypes (Aip, &InfoTypesBuffer, &InfoTypeBufferCount);\r
144 if (EFI_ERROR (Status) || (InfoTypesBuffer == NULL)) {\r
8873b174
YT
145 continue;\r
146 }\r
d1050b9d 147\r
8873b174
YT
148 //\r
149 // Check whether the AIP instance has Network boot information block.\r
150 //\r
151 Supported = FALSE;\r
152 for (TypeIndex = 0; TypeIndex < InfoTypeBufferCount; TypeIndex++) {\r
153 if (CompareGuid (&InfoTypesBuffer[TypeIndex], &gEfiAdapterInfoNetworkBootGuid)) {\r
154 Supported = TRUE;\r
155 break;\r
156 }\r
157 }\r
158\r
159 FreePool (InfoTypesBuffer);\r
160 if (!Supported) {\r
161 continue;\r
162 }\r
163\r
164 //\r
165 // We now have network boot information block.\r
166 //\r
167 InfoBlock = NULL;\r
168 InfoBlockSize = 0;\r
d1050b9d
MK
169 Status = Aip->GetInformation (Aip, &gEfiAdapterInfoNetworkBootGuid, &InfoBlock, &InfoBlockSize);\r
170 if (EFI_ERROR (Status) || (InfoBlock == NULL)) {\r
8873b174
YT
171 continue;\r
172 }\r
173\r
174 //\r
175 // Check whether the network boot policy matches.\r
176 //\r
d1050b9d 177 NetworkBoot = (EFI_ADAPTER_INFO_NETWORK_BOOT *)InfoBlock;\r
8873b174
YT
178 NetworkBootPolicy = PcdGet8 (PcdIScsiAIPNetworkBootPolicy);\r
179\r
180 if (NetworkBootPolicy == STOP_UEFI_ISCSI_IF_HBA_INSTALL_AIP) {\r
181 Status = EFI_SUCCESS;\r
182 goto Exit;\r
183 }\r
d1050b9d
MK
184\r
185 if ((((NetworkBootPolicy & STOP_UEFI_ISCSI_IF_AIP_SUPPORT_IP4) != 0) &&\r
8873b174 186 !NetworkBoot->iScsiIpv4BootCapablity) ||\r
d1050b9d 187 (((NetworkBootPolicy & STOP_UEFI_ISCSI_IF_AIP_SUPPORT_IP6) != 0) &&\r
8873b174 188 !NetworkBoot->iScsiIpv6BootCapablity) ||\r
d1050b9d 189 (((NetworkBootPolicy & STOP_UEFI_ISCSI_IF_AIP_SUPPORT_OFFLOAD) != 0) &&\r
8873b174 190 !NetworkBoot->OffloadCapability) ||\r
d1050b9d 191 (((NetworkBootPolicy & STOP_UEFI_ISCSI_IF_AIP_SUPPORT_MPIO) != 0) &&\r
8873b174 192 !NetworkBoot->iScsiMpioCapability) ||\r
d1050b9d 193 (((NetworkBootPolicy & STOP_UEFI_ISCSI_IF_AIP_CONFIGURED_IP4) != 0) &&\r
8873b174 194 !NetworkBoot->iScsiIpv4Boot) ||\r
d1050b9d
MK
195 (((NetworkBootPolicy & STOP_UEFI_ISCSI_IF_AIP_CONFIGURED_IP6) != 0) &&\r
196 !NetworkBoot->iScsiIpv6Boot))\r
197 {\r
8873b174
YT
198 FreePool (InfoBlock);\r
199 continue;\r
200 }\r
201\r
202 Status = EFI_SUCCESS;\r
203 goto Exit;\r
204 }\r
205\r
206 Status = EFI_NOT_FOUND;\r
207\r
208Exit:\r
209 if (InfoBlock != NULL) {\r
210 FreePool (InfoBlock);\r
211 }\r
d1050b9d 212\r
8873b174
YT
213 if (AipHandleBuffer != NULL) {\r
214 FreePool (AipHandleBuffer);\r
215 }\r
d1050b9d 216\r
8873b174
YT
217 return Status;\r
218}\r
4c5a5e0c 219\r
220/**\r
6879581d 221 Tests to see if this driver supports a given controller. This is the worker function for\r
222 IScsiIp4(6)DriverBindingSupported.\r
4c5a5e0c 223\r
224 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
f75a7f56
LG
225 @param[in] ControllerHandle The handle of the controller to test. This handle\r
226 must support a protocol interface that supplies\r
4c5a5e0c 227 an I/O abstraction to the driver.\r
f75a7f56
LG
228 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This\r
229 parameter is ignored by device drivers, and is optional for bus\r
230 drivers. For bus drivers, if this parameter is not NULL, then\r
231 the bus driver must determine if the bus controller specified\r
232 by ControllerHandle and the child controller specified\r
233 by RemainingDevicePath are both supported by this\r
4c5a5e0c 234 bus driver.\r
6879581d 235 @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6.\r
4c5a5e0c 236\r
237 @retval EFI_SUCCESS The device specified by ControllerHandle and\r
238 RemainingDevicePath is supported by the driver specified by This.\r
239 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and\r
240 RemainingDevicePath is already being managed by the driver\r
241 specified by This.\r
4c5a5e0c 242 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and\r
243 RemainingDevicePath is not supported by the driver specified by This.\r
244**/\r
245EFI_STATUS\r
246EFIAPI\r
6879581d 247IScsiSupported (\r
4c5a5e0c 248 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
249 IN EFI_HANDLE ControllerHandle,\r
6879581d 250 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL,\r
251 IN UINT8 IpVersion\r
4c5a5e0c 252 )\r
253{\r
d1050b9d
MK
254 EFI_STATUS Status;\r
255 EFI_GUID *IScsiServiceBindingGuid;\r
256 EFI_GUID *TcpServiceBindingGuid;\r
257 EFI_GUID *DhcpServiceBindingGuid;\r
258 EFI_GUID *DnsServiceBindingGuid;\r
4c5a5e0c 259\r
6879581d 260 if (IpVersion == IP_VERSION_4) {\r
d1050b9d
MK
261 IScsiServiceBindingGuid = &gIScsiV4PrivateGuid;\r
262 TcpServiceBindingGuid = &gEfiTcp4ServiceBindingProtocolGuid;\r
263 DhcpServiceBindingGuid = &gEfiDhcp4ServiceBindingProtocolGuid;\r
264 DnsServiceBindingGuid = &gEfiDns4ServiceBindingProtocolGuid;\r
4c5a5e0c 265 } else {\r
d1050b9d
MK
266 IScsiServiceBindingGuid = &gIScsiV6PrivateGuid;\r
267 TcpServiceBindingGuid = &gEfiTcp6ServiceBindingProtocolGuid;\r
268 DhcpServiceBindingGuid = &gEfiDhcp6ServiceBindingProtocolGuid;\r
269 DnsServiceBindingGuid = &gEfiDns6ServiceBindingProtocolGuid;\r
4c5a5e0c 270 }\r
271\r
272 Status = gBS->OpenProtocol (\r
273 ControllerHandle,\r
6879581d 274 IScsiServiceBindingGuid,\r
4c5a5e0c 275 NULL,\r
276 This->DriverBindingHandle,\r
277 ControllerHandle,\r
278 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
279 );\r
280 if (!EFI_ERROR (Status)) {\r
6879581d 281 return EFI_ALREADY_STARTED;\r
b7cc5bf1
WJ
282 }\r
283\r
284 Status = gBS->OpenProtocol (\r
285 ControllerHandle,\r
286 TcpServiceBindingGuid,\r
287 NULL,\r
288 This->DriverBindingHandle,\r
289 ControllerHandle,\r
290 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
291 );\r
292 if (EFI_ERROR (Status)) {\r
293 return EFI_UNSUPPORTED;\r
294 }\r
295\r
296 Status = IScsiIsDevicePathSupported (RemainingDevicePath);\r
297 if (EFI_ERROR (Status)) {\r
298 return EFI_UNSUPPORTED;\r
299 }\r
300\r
301 if (IScsiDhcpIsConfigured (ControllerHandle, IpVersion)) {\r
4c5a5e0c 302 Status = gBS->OpenProtocol (\r
303 ControllerHandle,\r
b7cc5bf1 304 DhcpServiceBindingGuid,\r
4c5a5e0c 305 NULL,\r
306 This->DriverBindingHandle,\r
307 ControllerHandle,\r
308 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
309 );\r
b7cc5bf1
WJ
310 if (EFI_ERROR (Status)) {\r
311 return EFI_UNSUPPORTED;\r
4c5a5e0c 312 }\r
313 }\r
eabc6e59
ZL
314\r
315 if (IScsiDnsIsConfigured (ControllerHandle)) {\r
316 Status = gBS->OpenProtocol (\r
317 ControllerHandle,\r
318 DnsServiceBindingGuid,\r
319 NULL,\r
320 This->DriverBindingHandle,\r
321 ControllerHandle,\r
322 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
323 );\r
324 if (EFI_ERROR (Status)) {\r
325 return EFI_UNSUPPORTED;\r
326 }\r
327 }\r
328\r
b7cc5bf1 329 return EFI_SUCCESS;\r
4c5a5e0c 330}\r
331\r
4c5a5e0c 332/**\r
333 Start to manage the controller. This is the worker function for\r
6879581d 334 IScsiIp4(6)DriverBindingStart.\r
4c5a5e0c 335\r
336 @param[in] Image Handle of the image.\r
337 @param[in] ControllerHandle Handle of the controller.\r
6879581d 338 @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6.\r
4c5a5e0c 339\r
efb56593 340 @retval EFI_SUCCESS This driver was started.\r
4c5a5e0c 341 @retval EFI_ALREADY_STARTED This driver is already running on this device.\r
342 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.\r
343 @retval EFI_NOT_FOUND There is no sufficient information to establish\r
344 the iScsi session.\r
7c275b3c 345 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
e590d29f
ZL
346 @retval EFI_DEVICE_ERROR Failed to get TCP connection device path.\r
347 @retval EFI_ACCESS_DENIED The protocol could not be removed from the Handle\r
348 because its interfaces are being used.\r
4c5a5e0c 349\r
350**/\r
351EFI_STATUS\r
352IScsiStart (\r
d1050b9d
MK
353 IN EFI_HANDLE Image,\r
354 IN EFI_HANDLE ControllerHandle,\r
355 IN UINT8 IpVersion\r
4c5a5e0c 356 )\r
357{\r
d1050b9d
MK
358 EFI_STATUS Status;\r
359 ISCSI_DRIVER_DATA *Private;\r
360 LIST_ENTRY *Entry;\r
361 LIST_ENTRY *NextEntry;\r
362 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptConfigData;\r
363 ISCSI_SESSION *Session;\r
364 UINT8 Index;\r
365 EFI_EXT_SCSI_PASS_THRU_PROTOCOL *ExistIScsiExtScsiPassThru;\r
366 ISCSI_DRIVER_DATA *ExistPrivate;\r
367 UINT8 *AttemptConfigOrder;\r
368 UINTN AttemptConfigOrderSize;\r
369 UINT8 BootSelected;\r
370 EFI_HANDLE *HandleBuffer;\r
371 UINTN NumberOfHandles;\r
372 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
373 EFI_GUID *IScsiPrivateGuid;\r
374 EFI_GUID *TcpServiceBindingGuid;\r
375 BOOLEAN NeedUpdate;\r
376 VOID *Interface;\r
377 EFI_GUID *ProtocolGuid;\r
378 UINT8 NetworkBootPolicy;\r
379 ISCSI_SESSION_CONFIG_NVDATA *NvData;\r
4c5a5e0c 380\r
381 //\r
382 // Test to see if iSCSI driver supports the given controller.\r
383 //\r
384\r
385 if (IpVersion == IP_VERSION_4) {\r
216f7970 386 IScsiPrivateGuid = &gIScsiV4PrivateGuid;\r
4c5a5e0c 387 TcpServiceBindingGuid = &gEfiTcp4ServiceBindingProtocolGuid;\r
388 ProtocolGuid = &gEfiTcp4ProtocolGuid;\r
389 } else if (IpVersion == IP_VERSION_6) {\r
216f7970 390 IScsiPrivateGuid = &gIScsiV6PrivateGuid;\r
4c5a5e0c 391 TcpServiceBindingGuid = &gEfiTcp6ServiceBindingProtocolGuid;\r
392 ProtocolGuid = &gEfiTcp6ProtocolGuid;\r
393 } else {\r
394 return EFI_INVALID_PARAMETER;\r
395 }\r
396\r
397 Status = gBS->OpenProtocol (\r
398 ControllerHandle,\r
399 IScsiPrivateGuid,\r
400 NULL,\r
401 Image,\r
402 ControllerHandle,\r
403 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
404 );\r
405 if (!EFI_ERROR (Status)) {\r
406 return EFI_ALREADY_STARTED;\r
407 }\r
408\r
409 Status = gBS->OpenProtocol (\r
410 ControllerHandle,\r
411 TcpServiceBindingGuid,\r
412 NULL,\r
413 Image,\r
414 ControllerHandle,\r
415 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
416 );\r
417 if (EFI_ERROR (Status)) {\r
418 return EFI_UNSUPPORTED;\r
419 }\r
420\r
8873b174 421 NetworkBootPolicy = PcdGet8 (PcdIScsiAIPNetworkBootPolicy);\r
483ee515 422 if (NetworkBootPolicy == ALWAYS_USE_ISCSI_HBA_AND_IGNORE_UEFI_ISCSI) {\r
423 return EFI_ABORTED;\r
424 }\r
425\r
426 if (NetworkBootPolicy != ALWAYS_USE_UEFI_ISCSI_AND_IGNORE_ISCSI_HBA) {\r
8873b174
YT
427 //\r
428 // Check existing iSCSI AIP.\r
429 //\r
430 Status = IScsiCheckAip ();\r
431 if (!EFI_ERROR (Status)) {\r
432 //\r
433 // Find iSCSI AIP with specified network boot policy. return EFI_ABORTED.\r
434 //\r
435 return EFI_ABORTED;\r
436 }\r
437 }\r
f75a7f56 438\r
4c5a5e0c 439 //\r
440 // Record the incoming NIC info.\r
441 //\r
6b08dd6e 442 Status = IScsiAddNic (ControllerHandle, Image);\r
4c5a5e0c 443 if (EFI_ERROR (Status)) {\r
444 return Status;\r
445 }\r
446\r
447 //\r
448 // Create the instance private data.\r
449 //\r
450 Private = IScsiCreateDriverData (Image, ControllerHandle);\r
451 if (Private == NULL) {\r
452 return EFI_OUT_OF_RESOURCES;\r
453 }\r
454\r
455 //\r
456 // Create a underlayer child instance, but not need to configure it. Just open ChildHandle\r
457 // via BY_DRIVER. That is, establishing the relationship between ControllerHandle and ChildHandle.\r
458 // Therefore, when DisconnectController(), especially VLAN virtual controller handle,\r
459 // IScsiDriverBindingStop() will be called.\r
460 //\r
461 Status = NetLibCreateServiceChild (\r
462 ControllerHandle,\r
463 Image,\r
464 TcpServiceBindingGuid,\r
465 &Private->ChildHandle\r
466 );\r
467\r
468 if (EFI_ERROR (Status)) {\r
469 goto ON_ERROR;\r
470 }\r
471\r
472 Status = gBS->OpenProtocol (\r
d63a52eb 473 Private->ChildHandle, /// Default Tcp child\r
4c5a5e0c 474 ProtocolGuid,\r
475 &Interface,\r
476 Image,\r
477 ControllerHandle,\r
478 EFI_OPEN_PROTOCOL_BY_DRIVER\r
479 );\r
f75a7f56 480\r
4c5a5e0c 481 if (EFI_ERROR (Status)) {\r
482 goto ON_ERROR;\r
483 }\r
484\r
485 //\r
f75a7f56 486 // Always install private protocol no matter what happens later. We need to\r
4c5a5e0c 487 // keep the relationship between ControllerHandle and ChildHandle.\r
488 //\r
489 Status = gBS->InstallProtocolInterface (\r
490 &ControllerHandle,\r
491 IScsiPrivateGuid,\r
492 EFI_NATIVE_INTERFACE,\r
493 &Private->IScsiIdentifier\r
494 );\r
495 if (EFI_ERROR (Status)) {\r
496 goto ON_ERROR;\r
497 }\r
f75a7f56 498\r
4c5a5e0c 499 if (IpVersion == IP_VERSION_4) {\r
500 mPrivate->Ipv6Flag = FALSE;\r
501 } else {\r
502 mPrivate->Ipv6Flag = TRUE;\r
503 }\r
504\r
505 //\r
506 // Get the current iSCSI configuration data.\r
507 //\r
508 Status = IScsiGetConfigData (Private);\r
509 if (EFI_ERROR (Status)) {\r
510 goto ON_ERROR;\r
511 }\r
512\r
513 //\r
514 // If there is already a successul attempt, check whether this attempt is the\r
515 // first "enabled for MPIO" attempt. If not, still try the first attempt.\r
516 // In single path mode, try all attempts.\r
517 //\r
518 ExistPrivate = NULL;\r
519 Status = EFI_NOT_FOUND;\r
520\r
521 if (mPrivate->OneSessionEstablished && mPrivate->EnableMpio) {\r
522 AttemptConfigData = NULL;\r
523 NET_LIST_FOR_EACH (Entry, &mPrivate->AttemptConfigs) {\r
d1050b9d 524 AttemptConfigData = NET_LIST_USER_STRUCT (Entry, ISCSI_ATTEMPT_CONFIG_NVDATA, Link);\r
4c5a5e0c 525 if (AttemptConfigData->SessionConfigData.Enabled == ISCSI_ENABLED_FOR_MPIO) {\r
526 break;\r
527 }\r
528 }\r
529\r
530 if (AttemptConfigData == NULL) {\r
531 goto ON_ERROR;\r
532 }\r
533\r
534 if (AttemptConfigData->AttemptConfigIndex == mPrivate->BootSelectedIndex) {\r
535 goto ON_EXIT;\r
536 }\r
537\r
538 //\r
539 // Uninstall the original ExtScsiPassThru first.\r
540 //\r
541\r
542 //\r
543 // Locate all ExtScsiPassThru protocol instances.\r
544 //\r
545 Status = gBS->LocateHandleBuffer (\r
546 ByProtocol,\r
547 &gEfiExtScsiPassThruProtocolGuid,\r
548 NULL,\r
549 &NumberOfHandles,\r
550 &HandleBuffer\r
551 );\r
552 if (EFI_ERROR (Status)) {\r
553 goto ON_ERROR;\r
554 }\r
555\r
556 //\r
557 // Find ExtScsiPassThru protocol instance produced by this driver.\r
558 //\r
559 ExistIScsiExtScsiPassThru = NULL;\r
560 for (Index = 0; Index < NumberOfHandles && ExistIScsiExtScsiPassThru == NULL; Index++) {\r
561 Status = gBS->HandleProtocol (\r
562 HandleBuffer[Index],\r
563 &gEfiDevicePathProtocolGuid,\r
d1050b9d 564 (VOID **)&DevicePath\r
4c5a5e0c 565 );\r
566 if (EFI_ERROR (Status)) {\r
567 continue;\r
568 }\r
569\r
570 while (!IsDevicePathEnd (DevicePath)) {\r
571 if ((DevicePath->Type == MESSAGING_DEVICE_PATH) && (DevicePath->SubType == MSG_MAC_ADDR_DP)) {\r
572 //\r
573 // Get the ExtScsiPassThru protocol instance.\r
574 //\r
575 Status = gBS->HandleProtocol (\r
576 HandleBuffer[Index],\r
577 &gEfiExtScsiPassThruProtocolGuid,\r
d1050b9d 578 (VOID **)&ExistIScsiExtScsiPassThru\r
4c5a5e0c 579 );\r
580 ASSERT_EFI_ERROR (Status);\r
581 break;\r
582 }\r
583\r
584 DevicePath = NextDevicePathNode (DevicePath);\r
585 }\r
586 }\r
587\r
588 FreePool (HandleBuffer);\r
589\r
590 if (ExistIScsiExtScsiPassThru == NULL) {\r
591 Status = EFI_NOT_FOUND;\r
592 goto ON_ERROR;\r
593 }\r
594\r
595 ExistPrivate = ISCSI_DRIVER_DATA_FROM_EXT_SCSI_PASS_THRU (ExistIScsiExtScsiPassThru);\r
596\r
597 Status = gBS->UninstallProtocolInterface (\r
598 ExistPrivate->ExtScsiPassThruHandle,\r
599 &gEfiExtScsiPassThruProtocolGuid,\r
600 &ExistPrivate->IScsiExtScsiPassThru\r
601 );\r
602 if (EFI_ERROR (Status)) {\r
603 goto ON_ERROR;\r
604 }\r
605 }\r
606\r
607 //\r
608 // Install the Ext SCSI PASS THRU protocol.\r
609 //\r
610 Status = gBS->InstallProtocolInterface (\r
611 &Private->ExtScsiPassThruHandle,\r
612 &gEfiExtScsiPassThruProtocolGuid,\r
613 EFI_NATIVE_INTERFACE,\r
614 &Private->IScsiExtScsiPassThru\r
615 );\r
616 if (EFI_ERROR (Status)) {\r
617 goto ON_ERROR;\r
618 }\r
619\r
620 BootSelected = 0;\r
621\r
622 NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &mPrivate->AttemptConfigs) {\r
623 AttemptConfigData = NET_LIST_USER_STRUCT (Entry, ISCSI_ATTEMPT_CONFIG_NVDATA, Link);\r
624 //\r
625 // Don't process the attempt that does not associate with the current NIC or\r
626 // this attempt is disabled or established.\r
627 //\r
d1050b9d
MK
628 if ((AttemptConfigData->NicIndex != mPrivate->CurrentNic) ||\r
629 (AttemptConfigData->SessionConfigData.Enabled == ISCSI_DISABLED) ||\r
630 AttemptConfigData->ValidPath)\r
631 {\r
4c5a5e0c 632 continue;\r
633 }\r
634\r
635 //\r
636 // In multipath mode, don't process attempts configured for single path.\r
637 // In default single path mode, don't process attempts configured for multipath.\r
638 //\r
639 if ((mPrivate->EnableMpio &&\r
d1050b9d 640 (AttemptConfigData->SessionConfigData.Enabled != ISCSI_ENABLED_FOR_MPIO)) ||\r
4c5a5e0c 641 (!mPrivate->EnableMpio &&\r
d1050b9d
MK
642 (AttemptConfigData->SessionConfigData.Enabled != ISCSI_ENABLED)))\r
643 {\r
4c5a5e0c 644 continue;\r
645 }\r
646\r
647 //\r
648 // Don't process the attempt that fails to get the init/target information from DHCP.\r
649 //\r
650 if (AttemptConfigData->SessionConfigData.InitiatorInfoFromDhcp &&\r
d1050b9d
MK
651 !AttemptConfigData->DhcpSuccess)\r
652 {\r
653 if (!mPrivate->EnableMpio && (mPrivate->ValidSinglePathCount > 0)) {\r
4c5a5e0c 654 mPrivate->ValidSinglePathCount--;\r
655 }\r
d1050b9d 656\r
4c5a5e0c 657 continue;\r
658 }\r
659\r
660 //\r
661 // Don't process the autoconfigure path if it is already established.\r
662 //\r
d1050b9d
MK
663 if ((AttemptConfigData->SessionConfigData.IpMode == IP_MODE_AUTOCONFIG) &&\r
664 AttemptConfigData->AutoConfigureSuccess)\r
665 {\r
4c5a5e0c 666 continue;\r
667 }\r
668\r
669 //\r
670 // Don't process the attempt if its IP mode is not in the current IP version.\r
671 //\r
672 if (!mPrivate->Ipv6Flag) {\r
673 if (AttemptConfigData->SessionConfigData.IpMode == IP_MODE_IP6) {\r
674 continue;\r
675 }\r
d1050b9d
MK
676\r
677 if ((AttemptConfigData->SessionConfigData.IpMode == IP_MODE_AUTOCONFIG) &&\r
678 (AttemptConfigData->AutoConfigureMode == IP_MODE_AUTOCONFIG_IP6))\r
679 {\r
4c5a5e0c 680 continue;\r
681 }\r
682 } else {\r
683 if (AttemptConfigData->SessionConfigData.IpMode == IP_MODE_IP4) {\r
684 continue;\r
685 }\r
d1050b9d
MK
686\r
687 if ((AttemptConfigData->SessionConfigData.IpMode == IP_MODE_AUTOCONFIG) &&\r
688 (AttemptConfigData->AutoConfigureMode == IP_MODE_AUTOCONFIG_IP4))\r
689 {\r
4c5a5e0c 690 continue;\r
691 }\r
692 }\r
693\r
694 //\r
695 // Fill in the Session and init it.\r
696 //\r
d1050b9d 697 Session = (ISCSI_SESSION *)AllocateZeroPool (sizeof (ISCSI_SESSION));\r
4c5a5e0c 698 if (Session == NULL) {\r
699 Status = EFI_OUT_OF_RESOURCES;\r
700 goto ON_ERROR;\r
701 }\r
702\r
703 Session->Private = Private;\r
704 Session->ConfigData = AttemptConfigData;\r
705 Session->AuthType = AttemptConfigData->AuthenticationType;\r
706\r
4c5a5e0c 707 UnicodeSPrint (\r
708 mPrivate->PortString,\r
d1050b9d 709 (UINTN)ISCSI_NAME_IFR_MAX_SIZE,\r
8d1f5e04 710 L"Attempt %d",\r
d1050b9d 711 (UINTN)AttemptConfigData->AttemptConfigIndex\r
4c5a5e0c 712 );\r
713\r
714 if (Session->AuthType == ISCSI_AUTH_TYPE_CHAP) {\r
715 Session->AuthData.CHAP.AuthConfig = &AttemptConfigData->AuthConfigData.CHAP;\r
716 }\r
717\r
718 IScsiSessionInit (Session, FALSE);\r
719\r
720 //\r
721 // Try to login and create an iSCSI session according to the configuration.\r
722 //\r
723 Status = IScsiSessionLogin (Session);\r
724 if (Status == EFI_MEDIA_CHANGED) {\r
725 //\r
726 // The specified target is not available, and the redirection information is\r
727 // received. Login the session again with the updated target address.\r
728 //\r
729 Status = IScsiSessionLogin (Session);\r
730 } else if (Status == EFI_NOT_READY) {\r
731 Status = IScsiSessionReLogin (Session);\r
732 }\r
733\r
a2d59ef2 734 //\r
efb56593 735 // Restore the original user setting which specifies the proxy/virtual iSCSI target to NV region.\r
a2d59ef2
YT
736 //\r
737 NvData = &AttemptConfigData->SessionConfigData;\r
738 if (NvData->RedirectFlag) {\r
739 NvData->TargetPort = NvData->OriginalTargetPort;\r
740 CopyMem (&NvData->TargetIp, &NvData->OriginalTargetIp, sizeof (EFI_IP_ADDRESS));\r
741 NvData->RedirectFlag = FALSE;\r
742\r
743 gRT->SetVariable (\r
744 mPrivate->PortString,\r
745 &gEfiIScsiInitiatorNameProtocolGuid,\r
746 ISCSI_CONFIG_VAR_ATTR,\r
747 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA),\r
748 AttemptConfigData\r
749 );\r
750 }\r
751\r
4c5a5e0c 752 if (EFI_ERROR (Status)) {\r
753 //\r
754 // In Single path mode, only the successful attempt will be recorded in iBFT;\r
755 // in multi-path mode, all the attempt entries in MPIO will be recorded in iBFT.\r
756 //\r
d1050b9d 757 if (!mPrivate->EnableMpio && (mPrivate->ValidSinglePathCount > 0)) {\r
4c5a5e0c 758 mPrivate->ValidSinglePathCount--;\r
759 }\r
760\r
761 FreePool (Session);\r
4c5a5e0c 762 } else {\r
763 AttemptConfigData->ValidPath = TRUE;\r
764\r
765 //\r
766 // Do not record the attempt in iBFT if it login with KRB5.\r
767 // TODO: record KRB5 attempt information in the iSCSI device path.\r
768 //\r
769 if (Session->AuthType == ISCSI_AUTH_TYPE_KRB) {\r
d1050b9d 770 if (!mPrivate->EnableMpio && (mPrivate->ValidSinglePathCount > 0)) {\r
4c5a5e0c 771 mPrivate->ValidSinglePathCount--;\r
772 }\r
773\r
774 AttemptConfigData->ValidiBFTPath = FALSE;\r
775 } else {\r
776 AttemptConfigData->ValidiBFTPath = TRUE;\r
777 }\r
778\r
779 //\r
780 // IScsi session success. Update the attempt state to NVR.\r
781 //\r
782 if (AttemptConfigData->SessionConfigData.IpMode == IP_MODE_AUTOCONFIG) {\r
87ce4210 783 AttemptConfigData->AutoConfigureSuccess = TRUE;\r
4c5a5e0c 784 }\r
785\r
786 gRT->SetVariable (\r
787 mPrivate->PortString,\r
788 &gEfiIScsiInitiatorNameProtocolGuid,\r
789 ISCSI_CONFIG_VAR_ATTR,\r
790 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA),\r
791 AttemptConfigData\r
792 );\r
793\r
794 //\r
795 // Select the first login session. Abort others.\r
796 //\r
797 if (Private->Session == NULL) {\r
798 Private->Session = Session;\r
799 BootSelected = AttemptConfigData->AttemptConfigIndex;\r
800 //\r
801 // Don't validate other attempt in multipath mode if one is success.\r
802 //\r
803 if (mPrivate->EnableMpio) {\r
804 break;\r
805 }\r
806 } else {\r
807 IScsiSessionAbort (Session);\r
808 FreePool (Session);\r
809 }\r
810 }\r
811 }\r
812\r
813 //\r
814 // All attempts configured for this driver instance are not valid.\r
815 //\r
816 if (Private->Session == NULL) {\r
817 Status = gBS->UninstallProtocolInterface (\r
818 Private->ExtScsiPassThruHandle,\r
819 &gEfiExtScsiPassThruProtocolGuid,\r
820 &Private->IScsiExtScsiPassThru\r
821 );\r
822 ASSERT_EFI_ERROR (Status);\r
823 Private->ExtScsiPassThruHandle = NULL;\r
824\r
825 //\r
826 // Reinstall the original ExtScsiPassThru back.\r
827 //\r
d1050b9d 828 if (mPrivate->OneSessionEstablished && (ExistPrivate != NULL)) {\r
4c5a5e0c 829 Status = gBS->InstallProtocolInterface (\r
830 &ExistPrivate->ExtScsiPassThruHandle,\r
831 &gEfiExtScsiPassThruProtocolGuid,\r
832 EFI_NATIVE_INTERFACE,\r
833 &ExistPrivate->IScsiExtScsiPassThru\r
834 );\r
835 if (EFI_ERROR (Status)) {\r
836 goto ON_ERROR;\r
837 }\r
838\r
839 goto ON_EXIT;\r
840 }\r
841\r
842 Status = EFI_NOT_FOUND;\r
843\r
844 goto ON_ERROR;\r
845 }\r
846\r
847 NeedUpdate = TRUE;\r
848 //\r
849 // More than one attempt successes.\r
850 //\r
d1050b9d 851 if ((Private->Session != NULL) && mPrivate->OneSessionEstablished) {\r
4c5a5e0c 852 AttemptConfigOrder = IScsiGetVariableAndSize (\r
853 L"AttemptOrder",\r
9bdc6592 854 &gIScsiConfigGuid,\r
4c5a5e0c 855 &AttemptConfigOrderSize\r
856 );\r
9c12f2d7
FS
857 if (AttemptConfigOrder == NULL) {\r
858 goto ON_ERROR;\r
859 }\r
d1050b9d 860\r
4c5a5e0c 861 for (Index = 0; Index < AttemptConfigOrderSize / sizeof (UINT8); Index++) {\r
d1050b9d
MK
862 if ((AttemptConfigOrder[Index] == mPrivate->BootSelectedIndex) ||\r
863 (AttemptConfigOrder[Index] == BootSelected))\r
864 {\r
4c5a5e0c 865 break;\r
866 }\r
867 }\r
868\r
869 if (mPrivate->EnableMpio) {\r
870 //\r
871 // Use the attempt in earlier order. Abort the later one in MPIO.\r
872 //\r
873 if (AttemptConfigOrder[Index] == mPrivate->BootSelectedIndex) {\r
874 IScsiSessionAbort (Private->Session);\r
875 FreePool (Private->Session);\r
876 Private->Session = NULL;\r
877 gBS->UninstallProtocolInterface (\r
878 Private->ExtScsiPassThruHandle,\r
879 &gEfiExtScsiPassThruProtocolGuid,\r
880 &Private->IScsiExtScsiPassThru\r
881 );\r
882 Private->ExtScsiPassThruHandle = NULL;\r
883\r
884 //\r
885 // Reinstall the original ExtScsiPassThru back.\r
886 //\r
887 Status = gBS->InstallProtocolInterface (\r
888 &ExistPrivate->ExtScsiPassThruHandle,\r
889 &gEfiExtScsiPassThruProtocolGuid,\r
890 EFI_NATIVE_INTERFACE,\r
891 &ExistPrivate->IScsiExtScsiPassThru\r
892 );\r
893 if (EFI_ERROR (Status)) {\r
894 goto ON_ERROR;\r
895 }\r
896\r
897 goto ON_EXIT;\r
898 } else {\r
9c12f2d7
FS
899 if (AttemptConfigOrder[Index] != BootSelected) {\r
900 goto ON_ERROR;\r
901 }\r
d1050b9d 902\r
4c5a5e0c 903 mPrivate->BootSelectedIndex = BootSelected;\r
904 //\r
905 // Clear the resource in ExistPrivate.\r
906 //\r
907 gBS->UninstallProtocolInterface (\r
908 ExistPrivate->Controller,\r
909 IScsiPrivateGuid,\r
910 &ExistPrivate->IScsiIdentifier\r
f75a7f56
LG
911 );\r
912\r
4c5a5e0c 913 IScsiRemoveNic (ExistPrivate->Controller);\r
914 if (ExistPrivate->Session != NULL) {\r
915 IScsiSessionAbort (ExistPrivate->Session);\r
916 }\r
917\r
89446d89
ZL
918 if (ExistPrivate->DevicePath != NULL) {\r
919 Status = gBS->UninstallProtocolInterface (\r
920 ExistPrivate->ExtScsiPassThruHandle,\r
921 &gEfiDevicePathProtocolGuid,\r
922 ExistPrivate->DevicePath\r
923 );\r
924 if (EFI_ERROR (Status)) {\r
925 goto ON_ERROR;\r
926 }\r
927\r
928 FreePool (ExistPrivate->DevicePath);\r
e590d29f 929 }\r
89446d89
ZL
930\r
931 gBS->CloseEvent (ExistPrivate->ExitBootServiceEvent);\r
932 FreePool (ExistPrivate);\r
4c5a5e0c 933 }\r
934 } else {\r
935 //\r
936 // Use the attempt in earlier order as boot selected in single path mode.\r
937 //\r
938 if (AttemptConfigOrder[Index] == mPrivate->BootSelectedIndex) {\r
939 NeedUpdate = FALSE;\r
940 }\r
941 }\r
4c5a5e0c 942 }\r
943\r
944 if (NeedUpdate) {\r
945 mPrivate->OneSessionEstablished = TRUE;\r
946 mPrivate->BootSelectedIndex = BootSelected;\r
947 }\r
948\r
949 //\r
950 // Duplicate the Session's tcp connection device path. The source port field\r
951 // will be set to zero as one iSCSI session is comprised of several iSCSI\r
952 // connections.\r
953 //\r
954 Private->DevicePath = IScsiGetTcpConnDevicePath (Private->Session);\r
955 if (Private->DevicePath == NULL) {\r
956 Status = EFI_DEVICE_ERROR;\r
957 goto ON_ERROR;\r
958 }\r
d1050b9d 959\r
4c5a5e0c 960 //\r
961 // Install the updated device path onto the ExtScsiPassThruHandle.\r
962 //\r
963 Status = gBS->InstallProtocolInterface (\r
964 &Private->ExtScsiPassThruHandle,\r
965 &gEfiDevicePathProtocolGuid,\r
966 EFI_NATIVE_INTERFACE,\r
967 Private->DevicePath\r
968 );\r
969 if (EFI_ERROR (Status)) {\r
970 goto ON_ERROR;\r
971 }\r
972\r
d63a52eb
WJ
973 //\r
974 // ISCSI children should share the default Tcp child, just open the default Tcp child via BY_CHILD_CONTROLLER.\r
975 //\r
976 Status = gBS->OpenProtocol (\r
977 Private->ChildHandle, /// Default Tcp child\r
978 ProtocolGuid,\r
979 &Interface,\r
980 Image,\r
981 Private->ExtScsiPassThruHandle,\r
982 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
f75a7f56 983 );\r
d63a52eb
WJ
984 if (EFI_ERROR (Status)) {\r
985 gBS->UninstallMultipleProtocolInterfaces (\r
986 Private->ExtScsiPassThruHandle,\r
987 &gEfiExtScsiPassThruProtocolGuid,\r
988 &Private->IScsiExtScsiPassThru,\r
989 &gEfiDevicePathProtocolGuid,\r
990 Private->DevicePath,\r
991 NULL\r
992 );\r
f75a7f56 993\r
d63a52eb
WJ
994 goto ON_ERROR;\r
995 }\r
996\r
4c5a5e0c 997ON_EXIT:\r
998\r
999 //\r
1000 // Update/Publish the iSCSI Boot Firmware Table.\r
1001 //\r
1002 if (mPrivate->BootSelectedIndex != 0) {\r
1003 IScsiPublishIbft ();\r
1004 }\r
1005\r
1006 return EFI_SUCCESS;\r
1007\r
1008ON_ERROR:\r
1009\r
1010 if (Private->Session != NULL) {\r
1011 IScsiSessionAbort (Private->Session);\r
1012 }\r
1013\r
1014 return Status;\r
1015}\r
1016\r
1017/**\r
6879581d 1018 Stops a device controller or a bus controller. This is the worker function for\r
1019 IScsiIp4(6)DriverBindingStop.\r
f75a7f56 1020\r
4c5a5e0c 1021 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
f75a7f56
LG
1022 @param[in] ControllerHandle A handle to the device being stopped. The handle must\r
1023 support a bus specific I/O protocol for the driver\r
4c5a5e0c 1024 to use to stop the device.\r
1025 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.\r
f75a7f56 1026 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL\r
4c5a5e0c 1027 if NumberOfChildren is 0.\r
6879581d 1028 @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6.\r
f75a7f56 1029\r
4c5a5e0c 1030 @retval EFI_SUCCESS The device was stopped.\r
1031 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.\r
e590d29f
ZL
1032 @retval EFI_INVALID_PARAMETER Child handle is NULL.\r
1033 @retval EFI_ACCESS_DENIED The protocol could not be removed from the Handle\r
1034 because its interfaces are being used.\r
4c5a5e0c 1035\r
1036**/\r
1037EFI_STATUS\r
1038EFIAPI\r
6879581d 1039IScsiStop (\r
4c5a5e0c 1040 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
1041 IN EFI_HANDLE ControllerHandle,\r
1042 IN UINTN NumberOfChildren,\r
6879581d 1043 IN EFI_HANDLE *ChildHandleBuffer OPTIONAL,\r
1044 IN UINT8 IpVersion\r
4c5a5e0c 1045 )\r
1046{\r
d1050b9d
MK
1047 EFI_HANDLE IScsiController;\r
1048 EFI_STATUS Status;\r
1049 ISCSI_PRIVATE_PROTOCOL *IScsiIdentifier;\r
1050 ISCSI_DRIVER_DATA *Private;\r
1051 EFI_EXT_SCSI_PASS_THRU_PROTOCOL *PassThru;\r
1052 ISCSI_CONNECTION *Conn;\r
1053 EFI_GUID *ProtocolGuid;\r
1054 EFI_GUID *TcpServiceBindingGuid;\r
1055 EFI_GUID *TcpProtocolGuid;\r
4c5a5e0c 1056\r
1057 if (NumberOfChildren != 0) {\r
1058 //\r
1059 // We should have only one child.\r
1060 //\r
1061 Status = gBS->OpenProtocol (\r
1062 ChildHandleBuffer[0],\r
1063 &gEfiExtScsiPassThruProtocolGuid,\r
d1050b9d 1064 (VOID **)&PassThru,\r
4c5a5e0c 1065 This->DriverBindingHandle,\r
1066 ControllerHandle,\r
1067 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
1068 );\r
1069 if (EFI_ERROR (Status)) {\r
1070 return EFI_DEVICE_ERROR;\r
1071 }\r
1072\r
1073 Private = ISCSI_DRIVER_DATA_FROM_EXT_SCSI_PASS_THRU (PassThru);\r
1074 Conn = NET_LIST_HEAD (&Private->Session->Conns, ISCSI_CONNECTION, Link);\r
1075\r
1076 //\r
1077 // Previously the TCP protocol is opened BY_CHILD_CONTROLLER. Just close\r
1078 // the protocol here, but do not uninstall the device path protocol and\r
1079 // EXT SCSI PASS THRU protocol installed on ExtScsiPassThruHandle.\r
1080 //\r
6879581d 1081 if (IpVersion == IP_VERSION_4) {\r
4c5a5e0c 1082 ProtocolGuid = &gEfiTcp4ProtocolGuid;\r
1083 } else {\r
1084 ProtocolGuid = &gEfiTcp6ProtocolGuid;\r
1085 }\r
1086\r
d63a52eb
WJ
1087 gBS->CloseProtocol (\r
1088 Private->ChildHandle,\r
1089 ProtocolGuid,\r
1090 Private->Image,\r
1091 Private->ExtScsiPassThruHandle\r
1092 );\r
f75a7f56 1093\r
4c5a5e0c 1094 gBS->CloseProtocol (\r
1095 Conn->TcpIo.Handle,\r
1096 ProtocolGuid,\r
1097 Private->Image,\r
1098 Private->ExtScsiPassThruHandle\r
1099 );\r
1100\r
1101 return EFI_SUCCESS;\r
1102 }\r
f75a7f56 1103\r
4c5a5e0c 1104 //\r
efb56593 1105 // Get the handle of the controller we are controlling.\r
4c5a5e0c 1106 //\r
6879581d 1107 if (IpVersion == IP_VERSION_4) {\r
d1050b9d
MK
1108 ProtocolGuid = &gIScsiV4PrivateGuid;\r
1109 TcpProtocolGuid = &gEfiTcp4ProtocolGuid;\r
1110 TcpServiceBindingGuid = &gEfiTcp4ServiceBindingProtocolGuid;\r
4c5a5e0c 1111 } else {\r
d1050b9d
MK
1112 ProtocolGuid = &gIScsiV6PrivateGuid;\r
1113 TcpProtocolGuid = &gEfiTcp6ProtocolGuid;\r
1114 TcpServiceBindingGuid = &gEfiTcp6ServiceBindingProtocolGuid;\r
4c5a5e0c 1115 }\r
d1050b9d 1116\r
6879581d 1117 IScsiController = NetLibGetNicHandle (ControllerHandle, TcpProtocolGuid);\r
1118 if (IScsiController == NULL) {\r
1119 return EFI_SUCCESS;\r
1120 }\r
4c5a5e0c 1121\r
1122 Status = gBS->OpenProtocol (\r
1123 IScsiController,\r
1124 ProtocolGuid,\r
d1050b9d 1125 (VOID **)&IScsiIdentifier,\r
4c5a5e0c 1126 This->DriverBindingHandle,\r
1127 ControllerHandle,\r
1128 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
1129 );\r
1130 if (EFI_ERROR (Status)) {\r
1131 return EFI_DEVICE_ERROR;\r
1132 }\r
1133\r
1134 Private = ISCSI_DRIVER_DATA_FROM_IDENTIFIER (IScsiIdentifier);\r
1135 ASSERT (Private != NULL);\r
1136\r
1137 if (Private->ChildHandle != NULL) {\r
1138 Status = gBS->CloseProtocol (\r
1139 Private->ChildHandle,\r
1140 TcpProtocolGuid,\r
1141 This->DriverBindingHandle,\r
1142 IScsiController\r
1143 );\r
f75a7f56 1144\r
4c5a5e0c 1145 ASSERT (!EFI_ERROR (Status));\r
1146\r
1147 Status = NetLibDestroyServiceChild (\r
1148 IScsiController,\r
1149 This->DriverBindingHandle,\r
1150 TcpServiceBindingGuid,\r
1151 Private->ChildHandle\r
1152 );\r
1153\r
1154 ASSERT (!EFI_ERROR (Status));\r
1155 }\r
1156\r
1157 gBS->UninstallProtocolInterface (\r
1158 IScsiController,\r
1159 ProtocolGuid,\r
1160 &Private->IScsiIdentifier\r
f75a7f56 1161 );\r
4c5a5e0c 1162\r
1163 //\r
1164 // Remove this NIC.\r
1165 //\r
1166 IScsiRemoveNic (IScsiController);\r
1167\r
1168 //\r
efb56593 1169 // Update the iSCSI Boot Firmware Table.\r
4c5a5e0c 1170 //\r
1171 IScsiPublishIbft ();\r
1172\r
1173 if (Private->Session != NULL) {\r
1174 IScsiSessionAbort (Private->Session);\r
1175 }\r
1176\r
e590d29f
ZL
1177 Status = IScsiCleanDriverData (Private);\r
1178\r
1179 if (EFI_ERROR (Status)) {\r
1180 return Status;\r
1181 }\r
4c5a5e0c 1182\r
1183 return EFI_SUCCESS;\r
1184}\r
1185\r
6879581d 1186/**\r
f75a7f56 1187 Tests to see if this driver supports a given controller. If a child device is provided,\r
6879581d 1188 it tests to see if this driver supports creating a handle for the specified child device.\r
1189\r
f75a7f56
LG
1190 This function checks to see if the driver specified by This supports the device specified by\r
1191 ControllerHandle. Drivers typically use the device path attached to\r
1192 ControllerHandle and/or the services from the bus I/O abstraction attached to\r
1193 ControllerHandle to determine if the driver supports ControllerHandle. This function\r
1194 may be called many times during platform initialization. In order to reduce boot times, the tests\r
1195 performed by this function must be very small and take as little time as possible to execute. This\r
1196 function must not change the state of any hardware devices, and this function must be aware that the\r
1197 device specified by ControllerHandle may already be managed by the same driver or a\r
1198 different driver. This function must match its calls to AllocatePages() with FreePages(),\r
1199 AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().\r
1200 Since ControllerHandle may have been previously started by the same driver, if a protocol is\r
1201 already in the opened state, then it must not be closed with CloseProtocol(). This is required\r
6879581d 1202 to guarantee the state of ControllerHandle is not modified by this function.\r
1203\r
1204 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
f75a7f56
LG
1205 @param[in] ControllerHandle The handle of the controller to test. This handle\r
1206 must support a protocol interface that supplies\r
6879581d 1207 an I/O abstraction to the driver.\r
f75a7f56
LG
1208 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This\r
1209 parameter is ignored by device drivers, and is optional for bus\r
1210 drivers. For bus drivers, if this parameter is not NULL, then\r
1211 the bus driver must determine if the bus controller specified\r
1212 by ControllerHandle and the child controller specified\r
1213 by RemainingDevicePath are both supported by this\r
6879581d 1214 bus driver.\r
1215\r
1216 @retval EFI_SUCCESS The device specified by ControllerHandle and\r
1217 RemainingDevicePath is supported by the driver specified by This.\r
1218 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and\r
1219 RemainingDevicePath is already managed by the driver\r
1220 specified by This.\r
1221 @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and\r
1222 RemainingDevicePath is already managed by a different\r
1223 driver or an application that requires exclusive access.\r
1224 Currently not implemented.\r
1225 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and\r
1226 RemainingDevicePath is not supported by the driver specified by This.\r
1227**/\r
1228EFI_STATUS\r
1229EFIAPI\r
1230IScsiIp4DriverBindingSupported (\r
1231 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
1232 IN EFI_HANDLE ControllerHandle,\r
1233 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
1234 )\r
1235{\r
1236 return IScsiSupported (\r
1237 This,\r
1238 ControllerHandle,\r
1239 RemainingDevicePath,\r
1240 IP_VERSION_4\r
1241 );\r
1242}\r
1243\r
1244/**\r
1245 Starts a device controller or a bus controller.\r
1246\r
1247 The Start() function is designed to be invoked from the EFI boot service ConnectController().\r
f75a7f56
LG
1248 As a result, much of the error checking on the parameters to Start() has been moved into this\r
1249 common boot service. It is legal to call Start() from other locations,\r
6879581d 1250 but the following calling restrictions must be followed or the system behavior will not be deterministic.\r
1251 1. ControllerHandle must be a valid EFI_HANDLE.\r
1252 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned\r
1253 EFI_DEVICE_PATH_PROTOCOL.\r
1254 3. Prior to calling Start(), the Supported() function for the driver specified by This must\r
f75a7f56 1255 have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.\r
6879581d 1256\r
1257 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
f75a7f56
LG
1258 @param[in] ControllerHandle The handle of the controller to start. This handle\r
1259 must support a protocol interface that supplies\r
6879581d 1260 an I/O abstraction to the driver.\r
f75a7f56
LG
1261 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This\r
1262 parameter is ignored by device drivers, and is optional for bus\r
1263 drivers. For a bus driver, if this parameter is NULL, then handles\r
1264 for all the children of Controller are created by this driver.\r
1265 If this parameter is not NULL and the first Device Path Node is\r
1266 not the End of Device Path Node, then only the handle for the\r
1267 child device specified by the first Device Path Node of\r
6879581d 1268 RemainingDevicePath is created by this driver.\r
f75a7f56 1269 If the first Device Path Node of RemainingDevicePath is\r
6879581d 1270 the End of Device Path Node, no child handle is created by this\r
1271 driver.\r
1272\r
1273 @retval EFI_SUCCESS The device was started.\r
1274 @retval EFI_DEVICE_ERROR The device could not be started due to a device error. Currently not implemented.\r
1275 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
1276 @retval Others The driver failed to start the device.\r
1277\r
1278**/\r
1279EFI_STATUS\r
1280EFIAPI\r
1281IScsiIp4DriverBindingStart (\r
1282 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
1283 IN EFI_HANDLE ControllerHandle,\r
1284 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
1285 )\r
1286{\r
d1050b9d 1287 EFI_STATUS Status;\r
6879581d 1288\r
1289 Status = IScsiStart (This->DriverBindingHandle, ControllerHandle, IP_VERSION_4);\r
1290 if (Status == EFI_ALREADY_STARTED) {\r
1291 Status = EFI_SUCCESS;\r
1292 }\r
1293\r
1294 return Status;\r
1295}\r
1296\r
1297/**\r
1298 Stops a device controller or a bus controller.\r
f75a7f56
LG
1299\r
1300 The Stop() function is designed to be invoked from the EFI boot service DisconnectController().\r
1301 As a result, much of the error checking on the parameters to Stop() has been moved\r
1302 into this common boot service. It is legal to call Stop() from other locations,\r
6879581d 1303 but the following calling restrictions must be followed or the system behavior will not be deterministic.\r
1304 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this\r
1305 same driver's Start() function.\r
1306 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid\r
1307 EFI_HANDLE. In addition, all of these handles must have been created in this driver's\r
1308 Start() function, and the Start() function must have called OpenProtocol() on\r
1309 ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.\r
f75a7f56 1310\r
6879581d 1311 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
f75a7f56
LG
1312 @param[in] ControllerHandle A handle to the device being stopped. The handle must\r
1313 support a bus specific I/O protocol for the driver\r
6879581d 1314 to use to stop the device.\r
1315 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.\r
f75a7f56 1316 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL\r
6879581d 1317 if NumberOfChildren is 0.\r
1318\r
1319 @retval EFI_SUCCESS The device was stopped.\r
1320 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.\r
1321\r
1322**/\r
1323EFI_STATUS\r
1324EFIAPI\r
1325IScsiIp4DriverBindingStop (\r
1326 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
1327 IN EFI_HANDLE ControllerHandle,\r
1328 IN UINTN NumberOfChildren,\r
1329 IN EFI_HANDLE *ChildHandleBuffer OPTIONAL\r
1330 )\r
1331{\r
1332 return IScsiStop (\r
1333 This,\r
1334 ControllerHandle,\r
1335 NumberOfChildren,\r
1336 ChildHandleBuffer,\r
1337 IP_VERSION_4\r
1338 );\r
1339}\r
1340\r
1341/**\r
f75a7f56 1342 Tests to see if this driver supports a given controller. If a child device is provided,\r
6879581d 1343 it tests to see if this driver supports creating a handle for the specified child device.\r
1344\r
f75a7f56
LG
1345 This function checks to see if the driver specified by This supports the device specified by\r
1346 ControllerHandle. Drivers typically use the device path attached to\r
1347 ControllerHandle and/or the services from the bus I/O abstraction attached to\r
1348 ControllerHandle to determine if the driver supports ControllerHandle. This function\r
1349 may be called many times during platform initialization. In order to reduce boot times, the tests\r
1350 performed by this function must be very small and take as little time as possible to execute. This\r
1351 function must not change the state of any hardware devices, and this function must be aware that the\r
1352 device specified by ControllerHandle may already be managed by the same driver or a\r
1353 different driver. This function must match its calls to AllocatePages() with FreePages(),\r
1354 AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().\r
1355 Since ControllerHandle may have been previously started by the same driver, if a protocol is\r
1356 already in the opened state, then it must not be closed with CloseProtocol(). This is required\r
6879581d 1357 to guarantee the state of ControllerHandle is not modified by this function.\r
1358\r
1359 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
f75a7f56
LG
1360 @param[in] ControllerHandle The handle of the controller to test. This handle\r
1361 must support a protocol interface that supplies\r
6879581d 1362 an I/O abstraction to the driver.\r
f75a7f56
LG
1363 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This\r
1364 parameter is ignored by device drivers, and is optional for bus\r
1365 drivers. For bus drivers, if this parameter is not NULL, then\r
1366 the bus driver must determine if the bus controller specified\r
1367 by ControllerHandle and the child controller specified\r
1368 by RemainingDevicePath are both supported by this\r
6879581d 1369 bus driver.\r
1370\r
1371 @retval EFI_SUCCESS The device specified by ControllerHandle and\r
1372 RemainingDevicePath is supported by the driver specified by This.\r
1373 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and\r
1374 RemainingDevicePath is already managed by the driver\r
1375 specified by This.\r
1376 @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and\r
1377 RemainingDevicePath is already managed by a different\r
1378 driver or an application that requires exclusive access.\r
1379 Currently not implemented.\r
1380 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and\r
1381 RemainingDevicePath is not supported by the driver specified by This.\r
1382**/\r
1383EFI_STATUS\r
1384EFIAPI\r
1385IScsiIp6DriverBindingSupported (\r
1386 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
1387 IN EFI_HANDLE ControllerHandle,\r
1388 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
1389 )\r
1390{\r
1391 return IScsiSupported (\r
1392 This,\r
1393 ControllerHandle,\r
1394 RemainingDevicePath,\r
1395 IP_VERSION_6\r
1396 );\r
1397}\r
1398\r
1399/**\r
1400 Starts a device controller or a bus controller.\r
1401\r
1402 The Start() function is designed to be invoked from the EFI boot service ConnectController().\r
f75a7f56
LG
1403 As a result, much of the error checking on the parameters to Start() has been moved into this\r
1404 common boot service. It is legal to call Start() from other locations,\r
6879581d 1405 but the following calling restrictions must be followed or the system behavior will not be deterministic.\r
1406 1. ControllerHandle must be a valid EFI_HANDLE.\r
1407 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned\r
1408 EFI_DEVICE_PATH_PROTOCOL.\r
1409 3. Prior to calling Start(), the Supported() function for the driver specified by This must\r
f75a7f56 1410 have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.\r
6879581d 1411\r
1412 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
f75a7f56
LG
1413 @param[in] ControllerHandle The handle of the controller to start. This handle\r
1414 must support a protocol interface that supplies\r
6879581d 1415 an I/O abstraction to the driver.\r
f75a7f56
LG
1416 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This\r
1417 parameter is ignored by device drivers, and is optional for bus\r
1418 drivers. For a bus driver, if this parameter is NULL, then handles\r
1419 for all the children of Controller are created by this driver.\r
1420 If this parameter is not NULL and the first Device Path Node is\r
1421 not the End of Device Path Node, then only the handle for the\r
1422 child device specified by the first Device Path Node of\r
6879581d 1423 RemainingDevicePath is created by this driver.\r
f75a7f56 1424 If the first Device Path Node of RemainingDevicePath is\r
6879581d 1425 the End of Device Path Node, no child handle is created by this\r
1426 driver.\r
1427\r
1428 @retval EFI_SUCCESS The device was started.\r
1429 @retval EFI_DEVICE_ERROR The device could not be started due to a device error. Currently not implemented.\r
1430 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
1431 @retval Others The driver failed to start the device.\r
1432\r
1433**/\r
1434EFI_STATUS\r
1435EFIAPI\r
1436IScsiIp6DriverBindingStart (\r
1437 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
1438 IN EFI_HANDLE ControllerHandle,\r
1439 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
1440 )\r
1441{\r
d1050b9d 1442 EFI_STATUS Status;\r
6879581d 1443\r
1444 Status = IScsiStart (This->DriverBindingHandle, ControllerHandle, IP_VERSION_6);\r
1445 if (Status == EFI_ALREADY_STARTED) {\r
1446 Status = EFI_SUCCESS;\r
1447 }\r
1448\r
1449 return Status;\r
1450}\r
1451\r
1452/**\r
1453 Stops a device controller or a bus controller.\r
f75a7f56
LG
1454\r
1455 The Stop() function is designed to be invoked from the EFI boot service DisconnectController().\r
1456 As a result, much of the error checking on the parameters to Stop() has been moved\r
1457 into this common boot service. It is legal to call Stop() from other locations,\r
6879581d 1458 but the following calling restrictions must be followed or the system behavior will not be deterministic.\r
1459 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this\r
1460 same driver's Start() function.\r
1461 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid\r
1462 EFI_HANDLE. In addition, all of these handles must have been created in this driver's\r
1463 Start() function, and the Start() function must have called OpenProtocol() on\r
1464 ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.\r
f75a7f56 1465\r
6879581d 1466 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
f75a7f56
LG
1467 @param[in] ControllerHandle A handle to the device being stopped. The handle must\r
1468 support a bus specific I/O protocol for the driver\r
6879581d 1469 to use to stop the device.\r
1470 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.\r
f75a7f56 1471 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL\r
6879581d 1472 if NumberOfChildren is 0.\r
1473\r
1474 @retval EFI_SUCCESS The device was stopped.\r
1475 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.\r
1476\r
1477**/\r
1478EFI_STATUS\r
1479EFIAPI\r
1480IScsiIp6DriverBindingStop (\r
1481 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
1482 IN EFI_HANDLE ControllerHandle,\r
1483 IN UINTN NumberOfChildren,\r
1484 IN EFI_HANDLE *ChildHandleBuffer OPTIONAL\r
1485 )\r
1486{\r
1487 return IScsiStop (\r
1488 This,\r
1489 ControllerHandle,\r
1490 NumberOfChildren,\r
1491 ChildHandleBuffer,\r
1492 IP_VERSION_6\r
1493 );\r
1494}\r
4c5a5e0c 1495\r
1496/**\r
1497 Unload the iSCSI driver.\r
1498\r
1499 @param[in] ImageHandle The handle of the driver image.\r
1500\r
1501 @retval EFI_SUCCESS The driver is unloaded.\r
1502 @retval EFI_DEVICE_ERROR An unexpected error occurred.\r
1503\r
1504**/\r
1505EFI_STATUS\r
1506EFIAPI\r
1507IScsiUnload (\r
1508 IN EFI_HANDLE ImageHandle\r
1509 )\r
1510{\r
d1050b9d
MK
1511 EFI_STATUS Status;\r
1512 UINTN DeviceHandleCount;\r
1513 EFI_HANDLE *DeviceHandleBuffer;\r
1514 UINTN Index;\r
1515 EFI_COMPONENT_NAME_PROTOCOL *ComponentName;\r
1516 EFI_COMPONENT_NAME2_PROTOCOL *ComponentName2;\r
4c5a5e0c 1517\r
1518 //\r
efb56593 1519 // Try to disconnect the driver from the devices it's controlling.\r
4c5a5e0c 1520 //\r
1521 Status = gBS->LocateHandleBuffer (\r
1522 AllHandles,\r
1523 NULL,\r
1524 NULL,\r
1525 &DeviceHandleCount,\r
1526 &DeviceHandleBuffer\r
1527 );\r
6879581d 1528 if (EFI_ERROR (Status)) {\r
1529 return Status;\r
1530 }\r
4c5a5e0c 1531\r
18b24f92
FS
1532 //\r
1533 // Disconnect the iSCSI4 driver from the controlled device.\r
1534 //\r
1535 for (Index = 0; Index < DeviceHandleCount; Index++) {\r
1536 Status = IScsiTestManagedDevice (\r
1537 DeviceHandleBuffer[Index],\r
1538 gIScsiIp4DriverBinding.DriverBindingHandle,\r
d1050b9d
MK
1539 &gEfiTcp4ProtocolGuid\r
1540 )\r
1541 ;\r
18b24f92
FS
1542 if (EFI_ERROR (Status)) {\r
1543 continue;\r
1544 }\r
d1050b9d 1545\r
18b24f92
FS
1546 Status = gBS->DisconnectController (\r
1547 DeviceHandleBuffer[Index],\r
1548 gIScsiIp4DriverBinding.DriverBindingHandle,\r
1549 NULL\r
1550 );\r
1551 if (EFI_ERROR (Status)) {\r
1552 goto ON_EXIT;\r
1553 }\r
1554 }\r
1555\r
1556 //\r
1557 // Disconnect the iSCSI6 driver from the controlled device.\r
1558 //\r
6879581d 1559 for (Index = 0; Index < DeviceHandleCount; Index++) {\r
18b24f92
FS
1560 Status = IScsiTestManagedDevice (\r
1561 DeviceHandleBuffer[Index],\r
1562 gIScsiIp6DriverBinding.DriverBindingHandle,\r
1563 &gEfiTcp6ProtocolGuid\r
1564 );\r
1565 if (EFI_ERROR (Status)) {\r
1566 continue;\r
1567 }\r
d1050b9d 1568\r
18b24f92
FS
1569 Status = gBS->DisconnectController (\r
1570 DeviceHandleBuffer[Index],\r
1571 gIScsiIp6DriverBinding.DriverBindingHandle,\r
1572 NULL\r
1573 );\r
1574 if (EFI_ERROR (Status)) {\r
1575 goto ON_EXIT;\r
1576 }\r
1577 }\r
1578\r
1579 //\r
1580 // Unload the iSCSI configuration form.\r
1581 //\r
1582 Status = IScsiConfigFormUnload (gIScsiIp4DriverBinding.DriverBindingHandle);\r
1583 if (EFI_ERROR (Status)) {\r
1584 goto ON_EXIT;\r
1585 }\r
f75a7f56 1586\r
18b24f92
FS
1587 //\r
1588 // Uninstall the protocols installed by iSCSI driver.\r
1589 //\r
1590 Status = gBS->UninstallMultipleProtocolInterfaces (\r
1591 ImageHandle,\r
1592 &gEfiAuthenticationInfoProtocolGuid,\r
1593 &gIScsiAuthenticationInfo,\r
1594 NULL\r
1595 );\r
1596 if (EFI_ERROR (Status)) {\r
1597 goto ON_EXIT;\r
1598 }\r
f75a7f56 1599\r
d1050b9d 1600 if (gIScsiControllerNameTable != NULL) {\r
18b24f92
FS
1601 Status = FreeUnicodeStringTable (gIScsiControllerNameTable);\r
1602 if (EFI_ERROR (Status)) {\r
1603 goto ON_EXIT;\r
1604 }\r
d1050b9d 1605\r
18b24f92
FS
1606 gIScsiControllerNameTable = NULL;\r
1607 }\r
1608\r
1609 //\r
1610 // Uninstall the ComponentName and ComponentName2 protocol from iSCSI4 driver binding handle\r
1611 // if it has been installed.\r
1612 //\r
1613 Status = gBS->HandleProtocol (\r
1614 gIScsiIp4DriverBinding.DriverBindingHandle,\r
1615 &gEfiComponentNameProtocolGuid,\r
d1050b9d 1616 (VOID **)&ComponentName\r
18b24f92
FS
1617 );\r
1618 if (!EFI_ERROR (Status)) {\r
1619 Status = gBS->UninstallMultipleProtocolInterfaces (\r
d1050b9d
MK
1620 gIScsiIp4DriverBinding.DriverBindingHandle,\r
1621 &gEfiComponentNameProtocolGuid,\r
1622 ComponentName,\r
1623 NULL\r
1624 );\r
18b24f92
FS
1625 if (EFI_ERROR (Status)) {\r
1626 goto ON_EXIT;\r
1627 }\r
1628 }\r
f75a7f56 1629\r
18b24f92
FS
1630 Status = gBS->HandleProtocol (\r
1631 gIScsiIp4DriverBinding.DriverBindingHandle,\r
1632 &gEfiComponentName2ProtocolGuid,\r
d1050b9d 1633 (VOID **)&ComponentName2\r
18b24f92
FS
1634 );\r
1635 if (!EFI_ERROR (Status)) {\r
1636 gBS->UninstallMultipleProtocolInterfaces (\r
1637 gIScsiIp4DriverBinding.DriverBindingHandle,\r
1638 &gEfiComponentName2ProtocolGuid,\r
1639 ComponentName2,\r
6879581d 1640 NULL\r
1641 );\r
18b24f92
FS
1642 if (EFI_ERROR (Status)) {\r
1643 goto ON_EXIT;\r
1644 }\r
4c5a5e0c 1645 }\r
6879581d 1646\r
4c5a5e0c 1647 //\r
18b24f92
FS
1648 // Uninstall the ComponentName and ComponentName2 protocol from iSCSI6 driver binding handle\r
1649 // if it has been installed.\r
4c5a5e0c 1650 //\r
18b24f92
FS
1651 Status = gBS->HandleProtocol (\r
1652 gIScsiIp6DriverBinding.DriverBindingHandle,\r
1653 &gEfiComponentNameProtocolGuid,\r
d1050b9d 1654 (VOID **)&ComponentName\r
18b24f92
FS
1655 );\r
1656 if (!EFI_ERROR (Status)) {\r
1657 Status = gBS->UninstallMultipleProtocolInterfaces (\r
d1050b9d
MK
1658 gIScsiIp6DriverBinding.DriverBindingHandle,\r
1659 &gEfiComponentNameProtocolGuid,\r
1660 ComponentName,\r
1661 NULL\r
1662 );\r
18b24f92
FS
1663 if (EFI_ERROR (Status)) {\r
1664 goto ON_EXIT;\r
1665 }\r
1666 }\r
f75a7f56 1667\r
18b24f92
FS
1668 Status = gBS->HandleProtocol (\r
1669 gIScsiIp6DriverBinding.DriverBindingHandle,\r
1670 &gEfiComponentName2ProtocolGuid,\r
d1050b9d 1671 (VOID **)&ComponentName2\r
18b24f92
FS
1672 );\r
1673 if (!EFI_ERROR (Status)) {\r
1674 gBS->UninstallMultipleProtocolInterfaces (\r
1675 gIScsiIp6DriverBinding.DriverBindingHandle,\r
1676 &gEfiComponentName2ProtocolGuid,\r
1677 ComponentName2,\r
1678 NULL\r
1679 );\r
1680 if (EFI_ERROR (Status)) {\r
1681 goto ON_EXIT;\r
1682 }\r
1683 }\r
4c5a5e0c 1684\r
1685 //\r
18b24f92 1686 // Uninstall the IScsiInitiatorNameProtocol and all the driver binding protocols.\r
4c5a5e0c 1687 //\r
18b24f92
FS
1688 Status = gBS->UninstallMultipleProtocolInterfaces (\r
1689 gIScsiIp4DriverBinding.DriverBindingHandle,\r
1690 &gEfiDriverBindingProtocolGuid,\r
1691 &gIScsiIp4DriverBinding,\r
1692 &gEfiIScsiInitiatorNameProtocolGuid,\r
1693 &gIScsiInitiatorName,\r
1694 NULL\r
1695 );\r
1696 if (EFI_ERROR (Status)) {\r
1697 goto ON_EXIT;\r
1698 }\r
216f7970 1699\r
18b24f92
FS
1700 Status = gBS->UninstallMultipleProtocolInterfaces (\r
1701 gIScsiIp6DriverBinding.DriverBindingHandle,\r
1702 &gEfiDriverBindingProtocolGuid,\r
1703 &gIScsiIp6DriverBinding,\r
1704 NULL\r
1705 );\r
1706\r
1707ON_EXIT:\r
1708\r
1709 if (DeviceHandleBuffer != NULL) {\r
1710 FreePool (DeviceHandleBuffer);\r
216f7970 1711 }\r
f75a7f56 1712\r
18b24f92 1713 return Status;\r
4c5a5e0c 1714}\r
1715\r
1716/**\r
1717 This is the declaration of an EFI image entry point. This entry point is\r
1718 the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including\r
1719 both device drivers and bus drivers.\r
f75a7f56 1720\r
4c5a5e0c 1721 The entry point for iSCSI driver which initializes the global variables and\r
1722 installs the driver binding, component name protocol, iSCSI initiator name\r
1723 protocol and Authentication Info protocol on its image.\r
f75a7f56 1724\r
4c5a5e0c 1725 @param[in] ImageHandle The firmware allocated handle for the UEFI image.\r
1726 @param[in] SystemTable A pointer to the EFI System Table.\r
1727\r
1728 @retval EFI_SUCCESS The operation completed successfully.\r
1729 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
1730\r
1731**/\r
1732EFI_STATUS\r
1733EFIAPI\r
1734IScsiDriverEntryPoint (\r
d1050b9d
MK
1735 IN EFI_HANDLE ImageHandle,\r
1736 IN EFI_SYSTEM_TABLE *SystemTable\r
4c5a5e0c 1737 )\r
1738{\r
1739 EFI_STATUS Status;\r
1740 EFI_ISCSI_INITIATOR_NAME_PROTOCOL *IScsiInitiatorName;\r
1741 EFI_AUTHENTICATION_INFO_PROTOCOL *AuthenticationInfo;\r
1742\r
1743 //\r
1744 // There should be only one EFI_ISCSI_INITIATOR_NAME_PROTOCOL.\r
1745 //\r
1746 Status = gBS->LocateProtocol (\r
1747 &gEfiIScsiInitiatorNameProtocolGuid,\r
1748 NULL,\r
d1050b9d 1749 (VOID **)&IScsiInitiatorName\r
4c5a5e0c 1750 );\r
1751 if (!EFI_ERROR (Status)) {\r
1752 return EFI_ACCESS_DENIED;\r
1753 }\r
1754\r
1755 //\r
1756 // Initialize the EFI Driver Library.\r
1757 //\r
1758 Status = EfiLibInstallDriverBindingComponentName2 (\r
1759 ImageHandle,\r
1760 SystemTable,\r
6879581d 1761 &gIScsiIp4DriverBinding,\r
4c5a5e0c 1762 ImageHandle,\r
1763 &gIScsiComponentName,\r
1764 &gIScsiComponentName2\r
1765 );\r
1766 if (EFI_ERROR (Status)) {\r
1767 return Status;\r
1768 }\r
1769\r
6879581d 1770 Status = EfiLibInstallDriverBindingComponentName2 (\r
1771 ImageHandle,\r
1772 SystemTable,\r
1773 &gIScsiIp6DriverBinding,\r
1774 NULL,\r
1775 &gIScsiComponentName,\r
1776 &gIScsiComponentName2\r
1777 );\r
1778 if (EFI_ERROR (Status)) {\r
1779 goto Error1;\r
1780 }\r
f75a7f56 1781\r
4c5a5e0c 1782 //\r
1783 // Install the iSCSI Initiator Name Protocol.\r
1784 //\r
1785 Status = gBS->InstallProtocolInterface (\r
1786 &ImageHandle,\r
1787 &gEfiIScsiInitiatorNameProtocolGuid,\r
1788 EFI_NATIVE_INTERFACE,\r
1789 &gIScsiInitiatorName\r
1790 );\r
1791 if (EFI_ERROR (Status)) {\r
6879581d 1792 goto Error2;\r
f75a7f56 1793 }\r
4c5a5e0c 1794\r
1795 //\r
1796 // Create the private data structures.\r
1797 //\r
903ce1d8
LE
1798 IScsiCHAPInitHashList ();\r
1799\r
4c5a5e0c 1800 mPrivate = AllocateZeroPool (sizeof (ISCSI_PRIVATE_DATA));\r
1801 if (mPrivate == NULL) {\r
1802 Status = EFI_OUT_OF_RESOURCES;\r
6879581d 1803 goto Error3;\r
4c5a5e0c 1804 }\r
1805\r
1806 InitializeListHead (&mPrivate->NicInfoList);\r
1807 InitializeListHead (&mPrivate->AttemptConfigs);\r
1808\r
1809 //\r
1810 // Initialize the configuration form of iSCSI.\r
1811 //\r
6879581d 1812 Status = IScsiConfigFormInit (gIScsiIp4DriverBinding.DriverBindingHandle);\r
4c5a5e0c 1813 if (EFI_ERROR (Status)) {\r
6879581d 1814 goto Error4;\r
4c5a5e0c 1815 }\r
1816\r
8d1f5e04
ZL
1817 //\r
1818 // Create the Maximum Attempts.\r
1819 //\r
1820 Status = IScsiCreateAttempts (PcdGet8 (PcdMaxIScsiAttemptNumber));\r
1821 if (EFI_ERROR (Status)) {\r
1822 goto Error5;\r
1823 }\r
1824\r
1825 //\r
1826 // Create Keywords for all the Attempts.\r
1827 //\r
1828 Status = IScsiCreateKeywords (PcdGet8 (PcdMaxIScsiAttemptNumber));\r
1829 if (EFI_ERROR (Status)) {\r
89648826 1830 goto Error6;\r
8d1f5e04
ZL
1831 }\r
1832\r
4c5a5e0c 1833 //\r
1834 // There should be only one EFI_AUTHENTICATION_INFO_PROTOCOL. If already exists,\r
1835 // do not produce the protocol instance.\r
1836 //\r
1837 Status = gBS->LocateProtocol (\r
1838 &gEfiAuthenticationInfoProtocolGuid,\r
1839 NULL,\r
d1050b9d 1840 (VOID **)&AuthenticationInfo\r
4c5a5e0c 1841 );\r
1842 if (Status == EFI_NOT_FOUND) {\r
1843 Status = gBS->InstallProtocolInterface (\r
1844 &ImageHandle,\r
1845 &gEfiAuthenticationInfoProtocolGuid,\r
1846 EFI_NATIVE_INTERFACE,\r
1847 &gIScsiAuthenticationInfo\r
1848 );\r
1849 if (EFI_ERROR (Status)) {\r
8d1f5e04 1850 goto Error6;\r
f75a7f56 1851 }\r
4c5a5e0c 1852 }\r
1853\r
1854 return EFI_SUCCESS;\r
1855\r
8d1f5e04 1856Error6:\r
89648826 1857 IScsiCleanAttemptVariable ();\r
4c5a5e0c 1858\r
8d1f5e04 1859Error5:\r
89648826 1860 IScsiConfigFormUnload (gIScsiIp4DriverBinding.DriverBindingHandle);\r
8d1f5e04 1861\r
6879581d 1862Error4:\r
89648826
JW
1863 if (mPrivate != NULL) {\r
1864 FreePool (mPrivate);\r
1865 mPrivate = NULL;\r
1866 }\r
4c5a5e0c 1867\r
6879581d 1868Error3:\r
4c5a5e0c 1869 gBS->UninstallMultipleProtocolInterfaces (\r
1870 ImageHandle,\r
1871 &gEfiIScsiInitiatorNameProtocolGuid,\r
1872 &gIScsiInitiatorName,\r
1873 NULL\r
1874 );\r
1875\r
6879581d 1876Error2:\r
15666b8c
AS
1877 EfiLibUninstallDriverBindingComponentName2 (\r
1878 &gIScsiIp6DriverBinding,\r
1879 &gIScsiComponentName,\r
1880 &gIScsiComponentName2\r
1881 );\r
6879581d 1882\r
4c5a5e0c 1883Error1:\r
15666b8c
AS
1884 EfiLibUninstallDriverBindingComponentName2 (\r
1885 &gIScsiIp4DriverBinding,\r
1886 &gIScsiComponentName,\r
1887 &gIScsiComponentName2\r
1888 );\r
4c5a5e0c 1889\r
1890 return Status;\r
1891}\r