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