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