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