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