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