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