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