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