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