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