]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Network/IScsiDxe/IScsiDriver.c
[Description]
[mirror_edk2.git] / MdeModulePkg / Universal / Network / IScsiDxe / IScsiDriver.c
1 /** @file
2 The entry point of IScsi driver
3
4 Copyright (c) 2004 - 2008, Intel Corporation
5 All rights reserved. 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 Module Name:
14
15 IScsiDriver.c
16
17 Abstract:
18 The entry point of IScsi driver
19
20 **/
21
22 #include "IScsiImpl.h"
23
24 EFI_DRIVER_BINDING_PROTOCOL gIScsiDriverBinding = {
25 IScsiDriverBindingSupported,
26 IScsiDriverBindingStart,
27 IScsiDriverBindingStop,
28 0xa,
29 NULL,
30 NULL
31 };
32
33 EFI_GUID mIScsiPrivateGuid = ISCSI_PRIVATE_GUID;
34
35 /**
36 Test to see if IScsi driver supports the given controller.
37
38 @param This[in] Protocol instance pointer.
39
40 @param ControllerHandle[in] Handle of controller to test.
41
42 @param RemainingDevicePath[in] Optional parameter use to pick a specific child device to start.
43
44 @retval EFI_SUCCES This driver supports the controller.
45
46 @retval EFI_ALREADY_STARTED This driver is already running on this device.
47
48 @retval EFI_UNSUPPORTED This driver doesn't support the controller.
49
50 **/
51 EFI_STATUS
52 EFIAPI
53 IScsiDriverBindingSupported (
54 IN EFI_DRIVER_BINDING_PROTOCOL * This,
55 IN EFI_HANDLE ControllerHandle,
56 IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL
57 )
58 {
59 EFI_STATUS Status;
60 EFI_DEVICE_PATH_PROTOCOL *CurrentDevicePath;
61
62 Status = gBS->OpenProtocol (
63 ControllerHandle,
64 &mIScsiPrivateGuid,
65 NULL,
66 This->DriverBindingHandle,
67 ControllerHandle,
68 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
69 );
70 if (!EFI_ERROR (Status)) {
71 return EFI_ALREADY_STARTED;
72 }
73
74 Status = gBS->OpenProtocol (
75 ControllerHandle,
76 &gEfiTcp4ServiceBindingProtocolGuid,
77 NULL,
78 This->DriverBindingHandle,
79 ControllerHandle,
80 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
81 );
82 if (EFI_ERROR (Status)) {
83 return EFI_UNSUPPORTED;
84 }
85
86 CurrentDevicePath = RemainingDevicePath;
87 if (CurrentDevicePath != NULL) {
88 while (!IsDevicePathEnd (CurrentDevicePath)) {
89 if ((CurrentDevicePath->Type == MESSAGING_DEVICE_PATH) && (CurrentDevicePath->SubType == MSG_ISCSI_DP)) {
90 return EFI_SUCCESS;
91 }
92
93 CurrentDevicePath = NextDevicePathNode (CurrentDevicePath);
94 }
95
96 return EFI_UNSUPPORTED;
97 }
98
99 return EFI_SUCCESS;
100 }
101
102 /**
103 Start to manage the controller.
104
105 @param This[in] Protocol instance pointer.
106
107 @param ControllerHandle[in] Handle of the controller.
108
109 @param RemainingDevicePath[in] Optional parameter use to pick a specific child device to start.
110
111 @retval EFI_SUCCES This driver supports this device.
112
113 @retval EFI_ALREADY_STARTED This driver is already running on this device.
114
115 **/
116 EFI_STATUS
117 EFIAPI
118 IScsiDriverBindingStart (
119 IN EFI_DRIVER_BINDING_PROTOCOL * This,
120 IN EFI_HANDLE ControllerHandle,
121 IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL
122 )
123 {
124 EFI_STATUS Status;
125 ISCSI_DRIVER_DATA *Private;
126
127 //
128 // Try to add a port configuration page for this controller.
129 //
130 IScsiConfigUpdateForm (This->DriverBindingHandle, ControllerHandle, TRUE);
131
132 Private = IScsiCreateDriverData (This->DriverBindingHandle, ControllerHandle);
133 if (Private == NULL) {
134 return EFI_OUT_OF_RESOURCES;
135 }
136 //
137 // Get the iSCSI configuration data of this controller.
138 //
139 Status = IScsiGetConfigData (Private);
140 if (EFI_ERROR (Status)) {
141 goto ON_ERROR;
142 }
143 //
144 // Try to login and create an iSCSI session according to the configuration.
145 //
146 Status = IScsiSessionLogin (Private);
147 if (Status == EFI_MEDIA_CHANGED) {
148 //
149 // The specified target is not available and the redirection information is
150 // got, login the session again with the updated target address.
151 //
152 Status = IScsiSessionLogin (Private);
153 }
154
155 if (EFI_ERROR (Status)) {
156 goto ON_ERROR;
157 }
158 //
159 // Duplicate the Session's tcp connection device path. The source port field
160 // will be set to zero as one iSCSI session is comprised of several iSCSI
161 // connections.
162 //
163 Private->DevicePath = IScsiGetTcpConnDevicePath (Private);
164 if (Private->DevicePath == NULL) {
165 goto ON_ERROR;
166 }
167 //
168 // Install the updated device path onto the ExtScsiPassThruHandle.
169 //
170 Status = gBS->InstallProtocolInterface (
171 &Private->ExtScsiPassThruHandle,
172 &gEfiDevicePathProtocolGuid,
173 EFI_NATIVE_INTERFACE,
174 Private->DevicePath
175 );
176 if (EFI_ERROR (Status)) {
177 goto ON_ERROR;
178 }
179 //
180 // Install the iSCSI private stuff as a flag to indicate this controller
181 // is already controlled by iSCSI driver.
182 //
183 Status = gBS->InstallProtocolInterface (
184 &ControllerHandle,
185 &mIScsiPrivateGuid,
186 EFI_NATIVE_INTERFACE,
187 &Private->IScsiIdentifier
188 );
189 if (EFI_ERROR (Status)) {
190 goto ON_ERROR;
191 }
192 //
193 // Update/Publish the iSCSI Boot Firmware Table.
194 //
195 IScsiPublishIbft ();
196
197 return EFI_SUCCESS;
198
199 ON_ERROR:
200
201 IScsiSessionAbort (&Private->Session);
202 IScsiCleanDriverData (Private);
203
204 return Status;
205 }
206
207 /**
208 Release the control of this controller and remove the IScsi functions.
209
210 @param This[in] Protocol instance pointer.
211
212 @param ControllerHandle[in] Handle of controller to stop.
213
214 @param NumberOfChildren[in] Not used.
215
216 @param ChildHandleBuffer[in] Not used.
217
218 @retval EFI_SUCCES This driver supports this device.
219
220 **/
221 EFI_STATUS
222 EFIAPI
223 IScsiDriverBindingStop (
224 IN EFI_DRIVER_BINDING_PROTOCOL *This,
225 IN EFI_HANDLE ControllerHandle,
226 IN UINTN NumberOfChildren,
227 IN EFI_HANDLE *ChildHandleBuffer
228 )
229 {
230 EFI_HANDLE IScsiController;
231 EFI_STATUS Status;
232 ISCSI_PRIVATE_PROTOCOL *IScsiIdentifier;
233 ISCSI_DRIVER_DATA *Private;
234 EFI_EXT_SCSI_PASS_THRU_PROTOCOL *PassThru;
235 ISCSI_CONNECTION *Conn;
236
237 if (NumberOfChildren != 0) {
238 //
239 // We should have only one child.
240 //
241 Status = gBS->OpenProtocol (
242 ChildHandleBuffer[0],
243 &gEfiExtScsiPassThruProtocolGuid,
244 (VOID **) &PassThru,
245 This->DriverBindingHandle,
246 ControllerHandle,
247 EFI_OPEN_PROTOCOL_GET_PROTOCOL
248 );
249 if (EFI_ERROR (Status)) {
250 return EFI_DEVICE_ERROR;
251 }
252
253 Private = ISCSI_DRIVER_DATA_FROM_EXT_SCSI_PASS_THRU (PassThru);
254 Conn = NET_LIST_HEAD (&Private->Session.Conns, ISCSI_CONNECTION, Link);
255
256 //
257 // Previously the TCP4 protocol is opened BY_CHILD_CONTROLLER. Just close
258 // the protocol here but not uninstall the device path protocol and
259 // EXT SCSI PASS THRU protocol installed on ExtScsiPassThruHandle.
260 //
261 gBS->CloseProtocol (
262 Conn->Tcp4Io.Handle,
263 &gEfiTcp4ProtocolGuid,
264 Private->Image,
265 Private->ExtScsiPassThruHandle
266 );
267
268 return EFI_SUCCESS;
269 }
270 //
271 // Get the handle of the controller we are controling.
272 //
273 IScsiController = NetLibGetNicHandle (ControllerHandle, &gEfiTcp4ProtocolGuid);
274
275 Status = gBS->OpenProtocol (
276 IScsiController,
277 &mIScsiPrivateGuid,
278 (VOID **)&IScsiIdentifier,
279 This->DriverBindingHandle,
280 ControllerHandle,
281 EFI_OPEN_PROTOCOL_GET_PROTOCOL
282 );
283 if (EFI_ERROR (Status)) {
284 return EFI_DEVICE_ERROR;
285 }
286
287 Private = ISCSI_DRIVER_DATA_FROM_IDENTIFIER (IScsiIdentifier);
288
289 //
290 // Uninstall the private protocol.
291 //
292 gBS->UninstallProtocolInterface (
293 IScsiController,
294 &mIScsiPrivateGuid,
295 &Private->IScsiIdentifier
296 );
297
298 //
299 // Update the iSCSI Boot Firware Table.
300 //
301 IScsiPublishIbft ();
302
303 IScsiSessionAbort (&Private->Session);
304 IScsiCleanDriverData (Private);
305
306 return EFI_SUCCESS;
307 }
308
309 /**
310 Unload the iSCSI driver.
311
312 @param ImageHandle[in] The handle of the driver image.
313
314 @retval EFI_SUCCESS The driver is unloaded.
315
316 @retval EFI_DEVICE_ERROR Some unexpected error happened.
317
318 **/
319 EFI_STATUS
320 EFIAPI
321 EfiIScsiUnload (
322 IN EFI_HANDLE ImageHandle
323 )
324 {
325 EFI_STATUS Status;
326 UINTN DeviceHandleCount;
327 EFI_HANDLE *DeviceHandleBuffer;
328 UINTN Index;
329
330 //
331 // Try to disonnect the driver from the devices it's controlling.
332 //
333 Status = gBS->LocateHandleBuffer (
334 AllHandles,
335 NULL,
336 NULL,
337 &DeviceHandleCount,
338 &DeviceHandleBuffer
339 );
340 if (!EFI_ERROR (Status)) {
341 for (Index = 0; Index < DeviceHandleCount; Index++) {
342 Status = gBS->DisconnectController (
343 DeviceHandleBuffer[Index],
344 ImageHandle,
345 NULL
346 );
347 }
348
349 if (DeviceHandleBuffer != NULL) {
350 gBS->FreePool (DeviceHandleBuffer);
351 }
352 }
353 //
354 // Unload the iSCSI configuration form.
355 //
356 IScsiConfigFormUnload (gIScsiDriverBinding.DriverBindingHandle);
357
358 //
359 // Uninstall the protocols installed by iSCSI driver.
360 //
361 Status = gBS->UninstallMultipleProtocolInterfaces (
362 ImageHandle,
363 &gEfiDriverBindingProtocolGuid,
364 &gIScsiDriverBinding,
365 &gEfiComponentName2ProtocolGuid,
366 &gIScsiComponentName2,
367 &gEfiComponentNameProtocolGuid,
368 &gIScsiComponentName,
369 &gEfiIScsiInitiatorNameProtocolGuid,
370 &gIScsiInitiatorName,
371 NULL
372 );
373
374 return Status;
375 }
376
377 /**
378 Initialize the global variables publish the driver binding protocol.
379
380 @param ImageHandle[in] The handle of the driver image.
381
382 @param SystemTable[in] The EFI system table.
383
384 @retval EFI_SUCCESS The protocols are installed.
385
386 @retval EFI_DEVICE_ERROR Some unexpected error happened.
387
388 **/
389 EFI_STATUS
390 EFIAPI
391 IScsiDriverEntryPoint (
392 IN EFI_HANDLE ImageHandle,
393 IN EFI_SYSTEM_TABLE *SystemTable
394 )
395 {
396 EFI_STATUS Status;
397 EFI_ISCSI_INITIATOR_NAME_PROTOCOL *IScsiInitiatorName;
398
399 //
400 // There should be only one EFI_ISCSI_INITIATOR_NAME_PROTOCOL.
401 //
402 Status = gBS->LocateProtocol (
403 &gEfiIScsiInitiatorNameProtocolGuid,
404 NULL,
405 (VOID**) &IScsiInitiatorName
406 );
407
408 if (!EFI_ERROR (Status)) {
409 return EFI_ACCESS_DENIED;
410 }
411
412 //
413 // Initialize the EFI Driver Library
414 //
415 Status = EfiLibInstallDriverBindingComponentName2 (
416 ImageHandle,
417 SystemTable,
418 &gIScsiDriverBinding,
419 ImageHandle,
420 &gIScsiComponentName,
421 &gIScsiComponentName2
422 );
423
424 if (!EFI_ERROR (Status)) {
425 //
426 // Install the iSCSI Initiator Name Protocol.
427 //
428 Status = gBS->InstallProtocolInterface (
429 &ImageHandle,
430 &gEfiIScsiInitiatorNameProtocolGuid,
431 EFI_NATIVE_INTERFACE,
432 &gIScsiInitiatorName
433 );
434 if (EFI_ERROR (Status)) {
435 gBS->UninstallMultipleProtocolInterfaces (
436 ImageHandle,
437 &gEfiDriverBindingProtocolGuid,
438 &gIScsiDriverBinding,
439 &gEfiComponentName2ProtocolGuid,
440 &gIScsiComponentName2,
441 &gEfiComponentNameProtocolGuid,
442 &gIScsiComponentName,
443 NULL
444 );
445 return Status;
446 }
447
448 //
449 // Initialize the configuration form of iSCSI.
450 //
451 Status = IScsiConfigFormInit (gIScsiDriverBinding.DriverBindingHandle);
452 if (EFI_ERROR (Status)) {
453 gBS->UninstallMultipleProtocolInterfaces (
454 ImageHandle,
455 &gEfiDriverBindingProtocolGuid,
456 &gIScsiDriverBinding,
457 &gEfiComponentName2ProtocolGuid,
458 &gIScsiComponentName2,
459 &gEfiComponentNameProtocolGuid,
460 &gIScsiComponentName,
461 &gEfiIScsiInitiatorNameProtocolGuid,
462 &gIScsiInitiatorName,
463 NULL
464 );
465 }
466 }
467 return Status;
468 }
469