]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Network/IScsiDxe/IScsiDriver.c
Clean up the private GUID definition in module Level.
[mirror_edk2.git] / MdeModulePkg / Universal / Network / IScsiDxe / IScsiDriver.c
CommitLineData
12618416 1/** @file\r
fd82de4e 2 The entry point of IScsi driver.\r
6a690e23 3\r
c8ad2d7a 4Copyright (c) 2004 - 2011, Intel Corporation. All rights reserved.<BR>\r
e5eed7d3 5This program and the accompanying materials\r
7a444476 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
6a690e23 12\r
12618416 13**/\r
6a690e23 14\r
15#include "IScsiImpl.h"\r
16\r
17EFI_DRIVER_BINDING_PROTOCOL gIScsiDriverBinding = {\r
18 IScsiDriverBindingSupported,\r
19 IScsiDriverBindingStart,\r
20 IScsiDriverBindingStop,\r
21 0xa,\r
22 NULL,\r
23 NULL\r
24};\r
25\r
fd82de4e 26/**\r
27 Tests to see if this driver supports a given controller. If a child device is provided, \r
28 it further tests to see if this driver supports creating a handle for the specified child device.\r
29\r
30 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
31 @param[in] ControllerHandle The handle of the controller to test. This handle \r
32 must support a protocol interface that supplies \r
33 an I/O abstraction to the driver.\r
34 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. \r
35 This parameter is ignored by device drivers, and is optional for bus drivers.\r
36\r
37\r
38 @retval EFI_SUCCESS The device specified by ControllerHandle and\r
39 RemainingDevicePath is supported by the driver specified by This.\r
40 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and\r
41 RemainingDevicePath is already being managed by the driver\r
42 specified by This.\r
43 @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and\r
44 RemainingDevicePath is already being managed by a different\r
45 driver or an application that requires exclusive acces.\r
46 Currently not implemented.\r
47 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and\r
48 RemainingDevicePath is not supported by the driver specified by This.\r
12618416 49**/\r
50EFI_STATUS\r
51EFIAPI\r
52IScsiDriverBindingSupported (\r
fd82de4e 53 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
12618416 54 IN EFI_HANDLE ControllerHandle,\r
fd82de4e 55 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
12618416 56 )\r
6a690e23 57{\r
58 EFI_STATUS Status;\r
59 EFI_DEVICE_PATH_PROTOCOL *CurrentDevicePath;\r
60\r
61 Status = gBS->OpenProtocol (\r
62 ControllerHandle,\r
c8ad2d7a 63 &gEfiCallerIdGuid,\r
6a690e23 64 NULL,\r
65 This->DriverBindingHandle,\r
66 ControllerHandle,\r
67 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
68 );\r
69 if (!EFI_ERROR (Status)) {\r
70 return EFI_ALREADY_STARTED;\r
71 }\r
72\r
73 Status = gBS->OpenProtocol (\r
74 ControllerHandle,\r
75 &gEfiTcp4ServiceBindingProtocolGuid,\r
76 NULL,\r
77 This->DriverBindingHandle,\r
78 ControllerHandle,\r
79 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
80 );\r
81 if (EFI_ERROR (Status)) {\r
82 return EFI_UNSUPPORTED;\r
83 }\r
84\r
85 CurrentDevicePath = RemainingDevicePath;\r
86 if (CurrentDevicePath != NULL) {\r
87 while (!IsDevicePathEnd (CurrentDevicePath)) {\r
88 if ((CurrentDevicePath->Type == MESSAGING_DEVICE_PATH) && (CurrentDevicePath->SubType == MSG_ISCSI_DP)) {\r
89 return EFI_SUCCESS;\r
90 }\r
91\r
92 CurrentDevicePath = NextDevicePathNode (CurrentDevicePath);\r
93 }\r
94\r
95 return EFI_UNSUPPORTED;\r
96 }\r
97\r
98 return EFI_SUCCESS;\r
99}\r
100\r
12618416 101/**\r
55a64ae0 102 Start this driver on ControllerHandle. \r
103 \r
104 The Start() function is designed to be invoked from the EFI boot service ConnectController(). \r
105 As a result, much of the error checking on the parameters to Start() has been moved into this \r
106 common boot service. It is legal to call Start() from other locations, but the following calling \r
107 restrictions must be followed or the system behavior will not be deterministic.\r
fd82de4e 108 1. ControllerHandle must be a valid EFI_HANDLE.\r
109 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned\r
110 EFI_DEVICE_PATH_PROTOCOL.\r
111 3. Prior to calling Start(), the Supported() function for the driver specified by This must\r
112 have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS. \r
113\r
114 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
115 @param[in] ControllerHandle The handle of the controller to start. This handle \r
116 must support a protocol interface that supplies \r
117 an I/O abstraction to the driver.\r
118 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. \r
119 This parameter is ignored by device drivers, and is optional for bus drivers.\r
120\r
121 @retval EFI_SUCCESS The device was started.\r
122 @retval EFI_DEVICE_ERROR The device could not be started due to a device error.\r
123 Currently not implemented.\r
124 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
125 @retval Others The driver failded to start the device.\r
12618416 126**/\r
6a690e23 127EFI_STATUS\r
128EFIAPI\r
129IScsiDriverBindingStart (\r
fd82de4e 130 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
6a690e23 131 IN EFI_HANDLE ControllerHandle,\r
fd82de4e 132 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
6a690e23 133 )\r
6a690e23 134{\r
135 EFI_STATUS Status;\r
136 ISCSI_DRIVER_DATA *Private;\r
fd627b16 137 VOID *Interface;\r
138\r
139 Private = IScsiCreateDriverData (This->DriverBindingHandle, ControllerHandle);\r
140 if (Private == NULL) {\r
141 return EFI_OUT_OF_RESOURCES;\r
142 }\r
143\r
144 //\r
145 // Create a underlayer child instance, but not need to configure it. Just open ChildHandle\r
146 // via BY_DRIVER. That is, establishing the relationship between ControllerHandle and ChildHandle.\r
147 // Therefore, when DisconnectController(), especially VLAN virtual controller handle,\r
148 // IScsiDriverBindingStop() will be called.\r
149 //\r
150 Status = NetLibCreateServiceChild (\r
151 ControllerHandle,\r
152 This->DriverBindingHandle,\r
153 &gEfiTcp4ServiceBindingProtocolGuid,\r
154 &Private->ChildHandle\r
155 );\r
156\r
157 if (EFI_ERROR (Status)) {\r
158 goto ON_ERROR;\r
159 }\r
160\r
161 Status = gBS->OpenProtocol (\r
162 Private->ChildHandle,\r
163 &gEfiTcp4ProtocolGuid,\r
164 &Interface,\r
165 This->DriverBindingHandle,\r
166 ControllerHandle,\r
167 EFI_OPEN_PROTOCOL_BY_DRIVER\r
168 );\r
169 if (EFI_ERROR (Status)) {\r
170 goto ON_ERROR;\r
171 }\r
172\r
173 //
174 // Always install private protocol no matter what happens later. We need to \r
175 // keep the relationship between ControllerHandle and ChildHandle.\r
176 //\r
177 Status = gBS->InstallProtocolInterface (\r
178 &ControllerHandle,\r
c8ad2d7a 179 &gEfiCallerIdGuid,\r
fd627b16 180 EFI_NATIVE_INTERFACE,\r
181 &Private->IScsiIdentifier\r
182 );\r
183 if (EFI_ERROR (Status)) {\r
184 goto ON_ERROR;\r
185 }\r
6a690e23 186\r
187 //\r
188 // Try to add a port configuration page for this controller.\r
189 //\r
190 IScsiConfigUpdateForm (This->DriverBindingHandle, ControllerHandle, TRUE);\r
191\r
6a690e23 192 //\r
193 // Get the iSCSI configuration data of this controller.\r
194 //\r
195 Status = IScsiGetConfigData (Private);\r
196 if (EFI_ERROR (Status)) {\r
197 goto ON_ERROR;\r
198 }\r
199 //\r
200 // Try to login and create an iSCSI session according to the configuration.\r
201 //\r
202 Status = IScsiSessionLogin (Private);\r
203 if (Status == EFI_MEDIA_CHANGED) {\r
204 //\r
205 // The specified target is not available and the redirection information is\r
206 // got, login the session again with the updated target address.\r
207 //\r
208 Status = IScsiSessionLogin (Private);\r
209 }\r
210\r
211 if (EFI_ERROR (Status)) {\r
212 goto ON_ERROR;\r
213 }\r
214 //\r
215 // Duplicate the Session's tcp connection device path. The source port field\r
216 // will be set to zero as one iSCSI session is comprised of several iSCSI\r
217 // connections.\r
218 //\r
219 Private->DevicePath = IScsiGetTcpConnDevicePath (Private);\r
220 if (Private->DevicePath == NULL) {\r
221 goto ON_ERROR;\r
222 }\r
223 //\r
224 // Install the updated device path onto the ExtScsiPassThruHandle.\r
225 //\r
226 Status = gBS->InstallProtocolInterface (\r
227 &Private->ExtScsiPassThruHandle,\r
228 &gEfiDevicePathProtocolGuid,\r
229 EFI_NATIVE_INTERFACE,\r
230 Private->DevicePath\r
231 );\r
232 if (EFI_ERROR (Status)) {\r
233 goto ON_ERROR;\r
234 }\r
fd627b16 235\r
6a690e23 236 //\r
237 // Update/Publish the iSCSI Boot Firmware Table.\r
238 //\r
239 IScsiPublishIbft ();\r
240\r
241 return EFI_SUCCESS;\r
242\r
243ON_ERROR:\r
244\r
245 IScsiSessionAbort (&Private->Session);\r
6a690e23 246\r
247 return Status;\r
248}\r
249\r
12618416 250/**\r
fd82de4e 251 Stop this driver on ControllerHandle. \r
252 \r
253 Release the control of this controller and remove the IScsi functions. The Stop()\r
254 function is designed to be invoked from the EFI boot service DisconnectController(). \r
255 As a result, much of the error checking on the parameters to Stop() has been moved \r
256 into this common boot service. It is legal to call Stop() from other locations, \r
257 but the following calling restrictions must be followed or the system behavior will not be deterministic.\r
258 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this\r
259 same driver's Start() function.\r
260 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid\r
261 EFI_HANDLE. In addition, all of these handles must have been created in this driver's\r
262 Start() function, and the Start() function must have called OpenProtocol() on\r
263 ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.\r
264 \r
265 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
266 @param[in] ControllerHandle A handle to the device being stopped. The handle must \r
267 support a bus specific I/O protocol for the driver \r
268 to use to stop the device.\r
269 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.Not used.\r
270 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL \r
271 if NumberOfChildren is 0.Not used.\r
272\r
273 @retval EFI_SUCCESS The device was stopped.\r
274 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.\r
12618416 275**/\r
6a690e23 276EFI_STATUS\r
277EFIAPI\r
278IScsiDriverBindingStop (\r
279 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
280 IN EFI_HANDLE ControllerHandle,\r
281 IN UINTN NumberOfChildren,\r
c5de0d55 282 IN EFI_HANDLE *ChildHandleBuffer OPTIONAL\r
6a690e23 283 )\r
6a690e23 284{\r
285 EFI_HANDLE IScsiController;\r
286 EFI_STATUS Status;\r
287 ISCSI_PRIVATE_PROTOCOL *IScsiIdentifier;\r
288 ISCSI_DRIVER_DATA *Private;\r
289 EFI_EXT_SCSI_PASS_THRU_PROTOCOL *PassThru;\r
290 ISCSI_CONNECTION *Conn;\r
291\r
292 if (NumberOfChildren != 0) {\r
293 //\r
294 // We should have only one child.\r
295 //\r
296 Status = gBS->OpenProtocol (\r
297 ChildHandleBuffer[0],\r
298 &gEfiExtScsiPassThruProtocolGuid,\r
299 (VOID **) &PassThru,\r
300 This->DriverBindingHandle,\r
301 ControllerHandle,\r
302 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
303 );\r
304 if (EFI_ERROR (Status)) {\r
305 return EFI_DEVICE_ERROR;\r
306 }\r
307\r
308 Private = ISCSI_DRIVER_DATA_FROM_EXT_SCSI_PASS_THRU (PassThru);\r
309 Conn = NET_LIST_HEAD (&Private->Session.Conns, ISCSI_CONNECTION, Link);\r
310\r
311 //\r
312 // Previously the TCP4 protocol is opened BY_CHILD_CONTROLLER. Just close\r
313 // the protocol here but not uninstall the device path protocol and\r
314 // EXT SCSI PASS THRU protocol installed on ExtScsiPassThruHandle.\r
315 //\r
316 gBS->CloseProtocol (\r
317 Conn->Tcp4Io.Handle,\r
318 &gEfiTcp4ProtocolGuid,\r
319 Private->Image,\r
320 Private->ExtScsiPassThruHandle\r
321 );\r
322\r
323 return EFI_SUCCESS;\r
324 }\r
325 //\r
326 // Get the handle of the controller we are controling.\r
327 //\r
328 IScsiController = NetLibGetNicHandle (ControllerHandle, &gEfiTcp4ProtocolGuid);\r
329\r
330 Status = gBS->OpenProtocol (\r
331 IScsiController,\r
c8ad2d7a 332 &gEfiCallerIdGuid,\r
6a690e23 333 (VOID **)&IScsiIdentifier,\r
334 This->DriverBindingHandle,\r
335 ControllerHandle,\r
336 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
337 );\r
338 if (EFI_ERROR (Status)) {\r
339 return EFI_DEVICE_ERROR;\r
340 }\r
341\r
342 Private = ISCSI_DRIVER_DATA_FROM_IDENTIFIER (IScsiIdentifier);\r
343\r
fd627b16 344 if (Private->ChildHandle != NULL) {\r
345 Status = gBS->CloseProtocol (\r
346 Private->ChildHandle,\r
347 &gEfiTcp4ProtocolGuid,\r
348 This->DriverBindingHandle,\r
349 IScsiController\r
350 );\r
351\r
352 ASSERT (!EFI_ERROR (Status));\r
353\r
354 Status = NetLibDestroyServiceChild (\r
355 IScsiController,\r
356 This->DriverBindingHandle,\r
357 &gEfiTcp4ServiceBindingProtocolGuid,\r
358 Private->ChildHandle\r
359 );\r
360 ASSERT (!EFI_ERROR (Status));\r
361 }\r
362\r
363 IScsiConfigUpdateForm (This->DriverBindingHandle, IScsiController, FALSE);\r
364\r
6a690e23 365 //\r
366 // Uninstall the private protocol.\r
367 //\r
368 gBS->UninstallProtocolInterface (\r
369 IScsiController,\r
c8ad2d7a 370 &gEfiCallerIdGuid,\r
6a690e23 371 &Private->IScsiIdentifier\r
372 );\r
373\r
374 //\r
375 // Update the iSCSI Boot Firware Table.\r
376 //\r
377 IScsiPublishIbft ();\r
378\r
379 IScsiSessionAbort (&Private->Session);\r
380 IScsiCleanDriverData (Private);\r
381\r
382 return EFI_SUCCESS;\r
383}\r
384\r
12618416 385/**\r
fd82de4e 386 Unloads an image(the iSCSI driver).\r
6a690e23 387\r
fd82de4e 388 @param[in] ImageHandle Handle that identifies the image to be unloaded.\r
6a690e23 389\r
fd82de4e 390 @retval EFI_SUCCESS The image has been unloaded.\r
963dbb30 391 @retval Others Other errors as indicated.\r
12618416 392**/\r
393EFI_STATUS\r
394EFIAPI\r
395EfiIScsiUnload (\r
396 IN EFI_HANDLE ImageHandle\r
397 )\r
6a690e23 398{\r
399 EFI_STATUS Status;\r
400 UINTN DeviceHandleCount;\r
401 EFI_HANDLE *DeviceHandleBuffer;\r
402 UINTN Index;\r
403\r
404 //\r
405 // Try to disonnect the driver from the devices it's controlling.\r
406 //\r
407 Status = gBS->LocateHandleBuffer (\r
408 AllHandles,\r
409 NULL,\r
410 NULL,\r
411 &DeviceHandleCount,\r
412 &DeviceHandleBuffer\r
413 );\r
414 if (!EFI_ERROR (Status)) {\r
415 for (Index = 0; Index < DeviceHandleCount; Index++) {\r
416 Status = gBS->DisconnectController (\r
417 DeviceHandleBuffer[Index],\r
418 ImageHandle,\r
419 NULL\r
420 );\r
421 }\r
422\r
423 if (DeviceHandleBuffer != NULL) {\r
766c7483 424 FreePool (DeviceHandleBuffer);\r
6a690e23 425 }\r
426 }\r
427 //\r
428 // Unload the iSCSI configuration form.\r
429 //\r
430 IScsiConfigFormUnload (gIScsiDriverBinding.DriverBindingHandle);\r
431\r
432 //\r
433 // Uninstall the protocols installed by iSCSI driver.\r
434 //\r
435 Status = gBS->UninstallMultipleProtocolInterfaces (\r
436 ImageHandle,\r
437 &gEfiDriverBindingProtocolGuid,\r
438 &gIScsiDriverBinding,\r
439 &gEfiComponentName2ProtocolGuid,\r
440 &gIScsiComponentName2,\r
441 &gEfiComponentNameProtocolGuid,\r
442 &gIScsiComponentName,\r
443 &gEfiIScsiInitiatorNameProtocolGuid,\r
444 &gIScsiInitiatorName,\r
445 NULL\r
446 );\r
447\r
448 return Status;\r
449}\r
450\r
12618416 451/**\r
fd82de4e 452 This is the declaration of an EFI image entry point. This entry point is\r
453 the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including\r
454 both device drivers and bus drivers. It initialize the global variables and \r
455 publish the driver binding protocol.\r
6a690e23 456\r
fd82de4e 457 @param[in] ImageHandle The firmware allocated handle for the UEFI image.\r
458 @param[in] SystemTable A pointer to the EFI System Table.\r
6a690e23 459\r
fd82de4e 460 @retval EFI_SUCCESS The operation completed successfully.\r
461 @retval EFI_ACCESS_DENIED EFI_ISCSI_INITIATOR_NAME_PROTOCOL was installed unexpectedly.\r
963dbb30 462 @retval Others Other errors as indicated.\r
12618416 463**/\r
464EFI_STATUS\r
465EFIAPI\r
466IScsiDriverEntryPoint (\r
467 IN EFI_HANDLE ImageHandle,\r
468 IN EFI_SYSTEM_TABLE *SystemTable\r
469 )\r
6a690e23 470{\r
f2a94e25 471 EFI_STATUS Status;\r
472 EFI_ISCSI_INITIATOR_NAME_PROTOCOL *IScsiInitiatorName;\r
473\r
474 //\r
475 // There should be only one EFI_ISCSI_INITIATOR_NAME_PROTOCOL.\r
476 //\r
477 Status = gBS->LocateProtocol (\r
478 &gEfiIScsiInitiatorNameProtocolGuid,\r
479 NULL,\r
b4df5011 480 (VOID**) &IScsiInitiatorName\r
f2a94e25 481 );\r
482\r
483 if (!EFI_ERROR (Status)) {\r
484 return EFI_ACCESS_DENIED;\r
485 }\r
6a690e23 486\r
487 //\r
488 // Initialize the EFI Driver Library\r
489 //\r
490 Status = EfiLibInstallDriverBindingComponentName2 (\r
491 ImageHandle,\r
492 SystemTable,\r
493 &gIScsiDriverBinding,\r
494 ImageHandle,\r
495 &gIScsiComponentName,\r
496 &gIScsiComponentName2\r
497 );\r
6a690e23 498\r
499 if (!EFI_ERROR (Status)) {\r
f2a94e25 500 //\r
501 // Install the iSCSI Initiator Name Protocol.\r
502 //\r
6a690e23 503 Status = gBS->InstallProtocolInterface (\r
504 &ImageHandle,\r
505 &gEfiIScsiInitiatorNameProtocolGuid,\r
506 EFI_NATIVE_INTERFACE,\r
507 &gIScsiInitiatorName\r
508 );\r
509 if (EFI_ERROR (Status)) {\r
510 gBS->UninstallMultipleProtocolInterfaces (\r
511 ImageHandle,\r
512 &gEfiDriverBindingProtocolGuid,\r
513 &gIScsiDriverBinding,\r
514 &gEfiComponentName2ProtocolGuid,\r
515 &gIScsiComponentName2,\r
516 &gEfiComponentNameProtocolGuid,\r
517 &gIScsiComponentName,\r
518 NULL\r
519 );\r
f2a94e25 520 return Status;\r
521 }\r
522 \r
523 //\r
524 // Initialize the configuration form of iSCSI.\r
525 //\r
963dbb30 526 Status = IScsiConfigFormInit ();\r
f2a94e25 527 if (EFI_ERROR (Status)) {\r
528 gBS->UninstallMultipleProtocolInterfaces (\r
529 ImageHandle,\r
530 &gEfiDriverBindingProtocolGuid,\r
531 &gIScsiDriverBinding,\r
532 &gEfiComponentName2ProtocolGuid,\r
533 &gIScsiComponentName2,\r
534 &gEfiComponentNameProtocolGuid,\r
535 &gIScsiComponentName,\r
536 &gEfiIScsiInitiatorNameProtocolGuid,\r
537 &gIScsiInitiatorName,\r
538 NULL\r
539 );\r
6a690e23 540 }\r
541 }\r
6a690e23 542 return Status;\r
543}\r
544\r