]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Network/Ip4ConfigDxe/Ip4ConfigDriver.c
1. Enabled IP4 layer auto configuration in case cable swap is detected.
[mirror_edk2.git] / MdeModulePkg / Universal / Network / Ip4ConfigDxe / Ip4ConfigDriver.c
1 /** @file
2 The driver binding for IP4 CONFIG protocol.
3
4 Copyright (c) 2006 - 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<BR>
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
16 #include "Ip4Config.h"
17 #include "Ip4ConfigNv.h"
18 #include "NicIp4Variable.h"
19
20 EFI_DRIVER_BINDING_PROTOCOL gIp4ConfigDriverBinding = {
21 Ip4ConfigDriverBindingSupported,
22 Ip4ConfigDriverBindingStart,
23 Ip4ConfigDriverBindingStop,
24 0xa,
25 NULL,
26 NULL
27 };
28
29 //
30 // The intance of template of IP4 Config private data
31 //
32 IP4_CONFIG_INSTANCE mIp4ConfigTemplate = {
33 IP4_CONFIG_INSTANCE_SIGNATURE,
34 NULL,
35 NULL,
36 (EFI_DEVICE_PATH_PROTOCOL *) NULL,
37 {
38 NULL,
39 NULL,
40 NULL
41 },
42 {
43 NULL,
44 NULL,
45 NULL
46 },
47 NULL,
48 (EFI_DEVICE_PATH_PROTOCOL *) NULL,
49 NULL,
50 {
51 FALSE,
52 FALSE,
53 {
54 0
55 },
56 {
57 0
58 },
59 {
60 0
61 }
62 },
63 0,
64 (EFI_MANAGED_NETWORK_PROTOCOL *) NULL,
65 NULL,
66 NULL,
67 NULL,
68 EFI_NOT_READY,
69 {
70 0,
71 0,
72 {
73 0
74 }
75 },
76 (CHAR16 *) NULL,
77 (NIC_IP4_CONFIG_INFO *) NULL,
78 (EFI_DHCP4_PROTOCOL *) NULL,
79 NULL,
80 NULL,
81 NULL,
82 TRUE
83 };
84
85 /**
86 The entry point for IP4 config driver which install the driver
87 binding and component name protocol on its image.
88
89 @param ImageHandle The image handle of the driver.
90 @param SystemTable The system table.
91
92 @retval EFI_SUCCES All the related protocols are installed on the driver.
93 @retval Others Failed to install protocols.
94
95 **/
96 EFI_STATUS
97 EFIAPI
98 Ip4ConfigDriverEntryPoint (
99 IN EFI_HANDLE ImageHandle,
100 IN EFI_SYSTEM_TABLE *SystemTable
101 )
102 {
103 return EfiLibInstallDriverBindingComponentName2 (
104 ImageHandle,
105 SystemTable,
106 &gIp4ConfigDriverBinding,
107 ImageHandle,
108 &gIp4ConfigComponentName,
109 &gIp4ConfigComponentName2
110 );
111 }
112
113
114 /**
115 Test to see if this driver supports ControllerHandle.
116
117 @param This Protocol instance pointer.
118 @param ControllerHandle Handle of device to test
119 @param RemainingDevicePath Optional parameter use to pick a specific child
120 device to start.
121
122 @retval EFI_SUCCES This driver supports this device
123 @retval EFI_ALREADY_STARTED This driver is already running on this device
124 @retval other This driver does not support this device
125
126 **/
127 EFI_STATUS
128 EFIAPI
129 Ip4ConfigDriverBindingSupported (
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
137 Status = gBS->OpenProtocol (
138 ControllerHandle,
139 &gEfiManagedNetworkServiceBindingProtocolGuid,
140 NULL,
141 This->DriverBindingHandle,
142 ControllerHandle,
143 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
144 );
145
146 return Status;
147 }
148
149
150 /**
151 Start this driver on ControllerHandle.
152
153 @param This Protocol instance pointer.
154 @param ControllerHandle Handle of device to bind driver to
155 @param RemainingDevicePath Optional parameter use to pick a specific child
156 device to start.
157
158 @retval EFI_SUCCES This driver is added to ControllerHandle
159 @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle
160 @retval other This driver does not support this device
161
162 **/
163 EFI_STATUS
164 EFIAPI
165 Ip4ConfigDriverBindingStart (
166 IN EFI_DRIVER_BINDING_PROTOCOL *This,
167 IN EFI_HANDLE ControllerHandle,
168 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
169 )
170 {
171 EFI_IP4_CONFIG_PROTOCOL *Ip4Config;
172 EFI_MANAGED_NETWORK_PROTOCOL *Mnp;
173 EFI_HANDLE MnpHandle;
174 IP4_CONFIG_INSTANCE *Instance;
175 EFI_SIMPLE_NETWORK_MODE SnpMode;
176 NIC_IP4_CONFIG_INFO *NicConfig;
177 EFI_STATUS Status;
178 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
179
180 Status = gBS->HandleProtocol (
181 ControllerHandle,
182 &gEfiDevicePathProtocolGuid,
183 (VOID **) &ParentDevicePath
184 );
185 if (EFI_ERROR (Status)) {
186 return Status;
187 }
188
189 //
190 // Check for multiple start.
191 //
192 Status = gBS->OpenProtocol (
193 ControllerHandle,
194 &gEfiIp4ConfigProtocolGuid,
195 (VOID **) &Ip4Config,
196 This->DriverBindingHandle,
197 ControllerHandle,
198 EFI_OPEN_PROTOCOL_GET_PROTOCOL
199 );
200
201 if (!EFI_ERROR (Status)) {
202 return EFI_ALREADY_STARTED;
203 }
204
205 //
206 // Create a MNP child
207 //
208 Mnp = NULL;
209 MnpHandle = NULL;
210 Instance = NULL;
211
212 Status = NetLibCreateServiceChild (
213 ControllerHandle,
214 This->DriverBindingHandle,
215 &gEfiManagedNetworkServiceBindingProtocolGuid,
216 &MnpHandle
217 );
218
219 if (EFI_ERROR (Status)) {
220 return Status;
221 }
222
223 Status = gBS->OpenProtocol (
224 MnpHandle,
225 &gEfiManagedNetworkProtocolGuid,
226 (VOID **) &Mnp,
227 This->DriverBindingHandle,
228 ControllerHandle,
229 EFI_OPEN_PROTOCOL_BY_DRIVER
230 );
231
232 if (EFI_ERROR (Status)) {
233 goto ON_ERROR;
234 }
235
236 //
237 // Allocate an instance then initialize it
238 //
239 Instance = AllocateCopyPool (sizeof (IP4_CONFIG_INSTANCE), &mIp4ConfigTemplate);
240
241 if (Instance == NULL) {
242 Status = EFI_OUT_OF_RESOURCES;
243 goto ON_ERROR;
244 }
245
246 Instance->Controller = ControllerHandle;
247 Instance->Image = This->DriverBindingHandle;
248 Instance->ParentDevicePath = ParentDevicePath;
249
250 CopyMem (&Instance->Ip4ConfigProtocol, &mIp4ConfigProtocolTemplate, sizeof (mIp4ConfigProtocolTemplate));
251
252 Instance->State = IP4_CONFIG_STATE_IDLE;
253 Instance->Mnp = Mnp;
254 Instance->MnpHandle = MnpHandle;
255
256 Status = Mnp->GetModeData (Mnp, NULL, &SnpMode);
257
258 if (EFI_ERROR (Status) && (Status != EFI_NOT_STARTED)) {
259 goto ON_ERROR;
260 }
261
262 Instance->NicAddr.Type = (UINT16) SnpMode.IfType;
263 Instance->NicAddr.Len = (UINT8) SnpMode.HwAddressSize;
264 CopyMem (&Instance->NicAddr.MacAddr, &SnpMode.CurrentAddress, Instance->NicAddr.Len);
265
266 //
267 // Add it to the global list, and compose the name
268 //
269 Status = NetLibGetMacString (Instance->Controller, Instance->Image, &Instance->MacString);
270 if (EFI_ERROR (Status)) {
271 goto ON_ERROR;
272 }
273
274 Status = Ip4ConfigDeviceInit (Instance);
275
276 //
277 // Install the IP4_CONFIG protocols
278 //
279 Status = gBS->InstallMultipleProtocolInterfaces (
280 &ControllerHandle,
281 &gEfiIp4ConfigProtocolGuid,
282 &Instance->Ip4ConfigProtocol,
283 NULL
284 );
285
286 if (EFI_ERROR (Status)) {
287 goto ON_ERROR;
288 }
289
290 //
291 // A dedicated timer is used to poll underlying media status.
292 //
293 Status = gBS->CreateEvent (
294 EVT_NOTIFY_SIGNAL | EVT_TIMER,
295 TPL_CALLBACK,
296 MediaChangeDetect,
297 Instance,
298 &Instance->Timer
299 );
300
301 if (EFI_ERROR (Status)) {
302 goto ON_ERROR;
303 }
304
305 //
306 // Get the previous configure parameters. If an error happend here,
307 // just ignore it because the driver should be able to operate.
308 //
309 NicConfig = Ip4ConfigReadVariable (Instance);
310 if (NicConfig != NULL) {
311 if (NicConfig->Perment) {
312 if (NicConfig->Source == IP4_CONFIG_SOURCE_STATIC) {
313 //
314 // Don't modify the permanent static configuration.
315 //
316 } else if (NicConfig->Source == IP4_CONFIG_SOURCE_DHCP) {
317 //
318 // Remove the previous acquired DHCP parameters.
319 //
320 ZeroMem (&NicConfig->Ip4Info, sizeof (EFI_IP4_IPCONFIG_DATA));
321 Ip4ConfigWriteVariable (Instance, NicConfig);
322 }
323 } else {
324 //
325 // Delete the non-permanent configuration.
326 //
327 Ip4ConfigWriteVariable (Instance, NULL);
328 }
329
330 FreePool (NicConfig);
331 }
332
333 return EFI_SUCCESS;
334
335 ON_ERROR:
336 if (Instance != NULL) {
337 FreePool (Instance);
338 }
339
340 if (Mnp != NULL) {
341 gBS->CloseProtocol (
342 MnpHandle,
343 &gEfiManagedNetworkProtocolGuid,
344 This->DriverBindingHandle,
345 ControllerHandle
346 );
347 }
348
349 NetLibDestroyServiceChild (
350 ControllerHandle,
351 This->DriverBindingHandle,
352 &gEfiManagedNetworkServiceBindingProtocolGuid,
353 MnpHandle
354 );
355
356 return Status;
357 }
358
359
360 /**
361 Stop this driver on ControllerHandle.
362
363 @param This Protocol instance pointer.
364 @param ControllerHandle Handle of device to stop driver on
365 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
366 children is zero stop the entire bus driver.
367 @param ChildHandleBuffer List of Child Handles to Stop.
368
369 @retval EFI_SUCCES This driver is removed ControllerHandle
370 @retval other This driver was not removed from this device
371
372 **/
373 EFI_STATUS
374 EFIAPI
375 Ip4ConfigDriverBindingStop (
376 IN EFI_DRIVER_BINDING_PROTOCOL *This,
377 IN EFI_HANDLE ControllerHandle,
378 IN UINTN NumberOfChildren,
379 IN EFI_HANDLE *ChildHandleBuffer
380 )
381 {
382 IP4_CONFIG_INSTANCE *Instance;
383 EFI_IP4_CONFIG_PROTOCOL *Ip4Config;
384 EFI_HANDLE NicHandle;
385 EFI_STATUS Status;
386
387 //
388 // IP4_CONFIG instance opens an MNP child. It may also create and open
389 // a DHCP child. If this is the DHCP handle, stop the DHCP process. If
390 // it is the MNP child, stop the whole driver.
391 //
392 //
393 NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiDhcp4ProtocolGuid);
394
395 if (NicHandle != NULL) {
396 //
397 // Get our context back then clean the DHCP up. Notify the user if necessary.
398 //
399 Status = gBS->OpenProtocol (
400 NicHandle,
401 &gEfiIp4ConfigProtocolGuid,
402 (VOID **) &Ip4Config,
403 This->DriverBindingHandle,
404 ControllerHandle,
405 EFI_OPEN_PROTOCOL_GET_PROTOCOL
406 );
407
408 if (EFI_ERROR (Status)) {
409 return Status;
410 }
411
412 Instance = IP4_CONFIG_INSTANCE_FROM_IP4CONFIG (Ip4Config);
413 ASSERT (ControllerHandle == Instance->Dhcp4Handle);
414
415 Ip4ConfigCleanDhcp4 (Instance);
416
417 Instance->State = IP4_CONFIG_STATE_CONFIGURED;
418 Instance->Result = EFI_DEVICE_ERROR;
419
420 if (Instance->DoneEvent != NULL) {
421 gBS->SignalEvent (Instance->DoneEvent);
422 }
423
424 return EFI_SUCCESS;
425 }
426
427 //
428 // This is a MNP handle, stop the whole driver
429 //
430 NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiManagedNetworkProtocolGuid);
431
432 if (NicHandle == NULL) {
433 return EFI_SUCCESS;
434 }
435
436 //
437 // Get our context back.
438 //
439 Status = gBS->OpenProtocol (
440 NicHandle,
441 &gEfiIp4ConfigProtocolGuid,
442 (VOID **) &Ip4Config,
443 This->DriverBindingHandle,
444 ControllerHandle,
445 EFI_OPEN_PROTOCOL_GET_PROTOCOL
446 );
447
448 if (EFI_ERROR (Status)) {
449 return Status;
450 }
451
452 Instance = IP4_CONFIG_INSTANCE_FROM_IP4CONFIG (Ip4Config);
453
454 Ip4ConfigDeviceUnload (Instance);
455
456 //
457 // Unload the protocols first to inform the top drivers
458 //
459 Status = gBS->UninstallMultipleProtocolInterfaces (
460 NicHandle,
461 &gEfiIp4ConfigProtocolGuid,
462 &Instance->Ip4ConfigProtocol,
463 NULL
464 );
465
466 if (EFI_ERROR (Status)) {
467 return Status;
468 }
469
470 //
471 // Release all the resources
472 //
473 if (Instance->MnpHandle != NULL) {
474 gBS->CloseProtocol (
475 Instance->MnpHandle,
476 &gEfiManagedNetworkProtocolGuid,
477 This->DriverBindingHandle,
478 NicHandle
479 );
480
481 NetLibDestroyServiceChild (
482 NicHandle,
483 Instance->Image,
484 &gEfiManagedNetworkServiceBindingProtocolGuid,
485 Instance->MnpHandle
486 );
487
488 Instance->Mnp = NULL;
489 Instance->MnpHandle = NULL;
490 }
491
492 if (Instance->MacString != NULL) {
493 FreePool (Instance->MacString);
494 }
495
496 if (Instance->Timer != NULL) {
497 gBS->SetTimer (Instance->Timer, TimerCancel, 0);
498 gBS->CloseEvent (Instance->Timer);
499 Instance->Timer = NULL;
500 }
501
502 Ip4ConfigCleanConfig (Instance);
503 FreePool (Instance);
504
505 return EFI_SUCCESS;
506 }