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