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