]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Network/Ip4ConfigDxe/Ip4Config.c
Scrubbed some code for Ip4ConfigDxe.
[mirror_edk2.git] / MdeModulePkg / Universal / Network / Ip4ConfigDxe / Ip4Config.c
CommitLineData
b2570da8 1/** @file\r
402fa70f 2 This code implements the IP4Config and NicIp4Config protocols.\r
b2570da8 3\r
402fa70f 4Copyright (c) 2006 - 2008, Intel Corporation.<BR> \r
b2570da8 5All rights reserved. This program and the accompanying materials\r
6are licensed and made available under the terms and conditions of the BSD License\r
402fa70f 7which accompanies this distribution. The full text of the license may be found at<BR>\r
b2570da8 8http://opensource.org/licenses/bsd-license.php\r
9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
b2570da8 13**/\r
14\r
15#include "Ip4Config.h"\r
16\r
17IP4_CONFIG_INSTANCE *mIp4ConfigNicList[MAX_IP4_CONFIG_IN_VARIABLE];\r
18\r
7bce0c5a 19/**\r
20 Callback function when DHCP process finished. It will save the\r
21 retrieved IP configure parameter from DHCP to the NVRam.\r
22\r
23 @param Event The callback event\r
24 @param Context Opaque context to the callback\r
25\r
26 @return None\r
27\r
28**/\r
b2570da8 29VOID\r
30EFIAPI\r
31Ip4ConfigOnDhcp4Complete (\r
32 IN EFI_EVENT Event,\r
33 IN VOID *Context\r
34 );\r
35\r
36\r
37/**\r
38 Return the name and MAC address for the NIC. The Name, if not NULL,\r
39 has at least IP4_NIC_NAME_LENGTH bytes.\r
40\r
41 @param This The NIC IP4 CONFIG protocol\r
42 @param Name The buffer to return the name\r
43 @param NicAddr The buffer to return the MAC addr\r
44\r
45 @retval EFI_INVALID_PARAMETER This is NULL\r
46 @retval EFI_SUCCESS The name or address of the NIC are returned.\r
47\r
48**/\r
b2570da8 49EFI_STATUS\r
50EFIAPI\r
51EfiNicIp4ConfigGetName (\r
52 IN EFI_NIC_IP4_CONFIG_PROTOCOL *This,\r
53 IN UINT16 *Name, OPTIONAL\r
54 IN NIC_ADDR *NicAddr OPTIONAL\r
55 )\r
56{\r
57 IP4_CONFIG_INSTANCE *Instance;\r
58\r
59 if (This == NULL) {\r
60 return EFI_INVALID_PARAMETER;\r
61 }\r
62\r
63 Instance = IP4_CONFIG_INSTANCE_FROM_NIC_IP4CONFIG (This);\r
64\r
65 if (Name != NULL) {\r
e48e37fc 66 CopyMem (Name, Instance->NicName, IP4_NIC_NAME_LENGTH);\r
b2570da8 67 }\r
68\r
69 if (NicAddr != NULL) {\r
687a2e5f 70 CopyMem (NicAddr, &Instance->NicAddr, sizeof (*NicAddr));\r
b2570da8 71 }\r
72\r
73 return EFI_SUCCESS;\r
74}\r
75\r
76\r
77/**\r
78 Get the NIC's configure information from the IP4 configure variable.\r
79 It will remove the invalid variable.\r
80\r
81 @param NicAddr The NIC to check\r
82\r
83 @return NULL if no configure for the NIC in the variable, or it is invalid.\r
84 @return Otherwise the NIC's IP configure parameter.\r
85\r
86**/\r
87NIC_IP4_CONFIG_INFO *\r
88Ip4ConfigGetNicInfo (\r
89 IN NIC_ADDR *NicAddr\r
90 )\r
91{\r
92 IP4_CONFIG_VARIABLE *Variable;\r
93 IP4_CONFIG_VARIABLE *NewVariable;\r
94 NIC_IP4_CONFIG_INFO *Config;\r
95\r
96 //\r
97 // Read the configuration parameter for this NicAddr from\r
98 // the EFI variable\r
99 //\r
100 Variable = Ip4ConfigReadVariable ();\r
101\r
102 if (Variable == NULL) {\r
103 return NULL;\r
104 }\r
105\r
106 Config = Ip4ConfigFindNicVariable (Variable, NicAddr);\r
107\r
108 if (Config == NULL) {\r
e48e37fc 109 gBS->FreePool (Variable);\r
b2570da8 110 return NULL;\r
111 }\r
112\r
113 //\r
114 // Validate the configuration, if the configuration is invalid,\r
115 // remove it from the variable.\r
116 //\r
117 if (!Ip4ConfigIsValid (Config)) {\r
118 NewVariable = Ip4ConfigModifyVariable (Variable, &Config->NicAddr, NULL);\r
119 Ip4ConfigWriteVariable (NewVariable);\r
120\r
121 if (NewVariable != NULL) {\r
e48e37fc 122 gBS->FreePool (NewVariable);\r
b2570da8 123 };\r
124\r
e48e37fc 125 gBS->FreePool (Config);\r
b2570da8 126 Config = NULL;\r
127 }\r
128\r
e48e37fc 129 gBS->FreePool (Variable);\r
b2570da8 130 return Config;\r
131}\r
132\r
133\r
134/**\r
135 Get the configure parameter for this NIC.\r
136\r
137 @param This The NIC IP4 CONFIG protocol\r
138 @param ConfigLen The length of the NicConfig buffer.\r
139 @param NicConfig The buffer to receive the NIC's configure\r
140 parameter.\r
141\r
142 @retval EFI_INVALID_PARAMETER This or ConfigLen is NULL\r
143 @retval EFI_NOT_FOUND There is no configure parameter for the NIC in\r
144 NVRam.\r
145\r
146**/\r
147EFI_STATUS\r
148EFIAPI\r
149EfiNicIp4ConfigGetInfo (\r
150 IN EFI_NIC_IP4_CONFIG_PROTOCOL *This,\r
151 IN OUT UINTN *ConfigLen,\r
152 OUT NIC_IP4_CONFIG_INFO *NicConfig\r
153 )\r
154{\r
155 IP4_CONFIG_INSTANCE *Instance;\r
156 NIC_IP4_CONFIG_INFO *Config;\r
157 EFI_STATUS Status;\r
158 UINTN Len;\r
159\r
160 if ((This == NULL) || (ConfigLen == NULL)) {\r
161 return EFI_INVALID_PARAMETER;\r
162 }\r
163\r
164 //\r
165 // Read the Nic's configuration parameter from variable\r
166 //\r
167 Instance = IP4_CONFIG_INSTANCE_FROM_NIC_IP4CONFIG (This);\r
168 Config = Ip4ConfigGetNicInfo (&Instance->NicAddr);\r
169\r
170 if (Config == NULL) {\r
171 return EFI_NOT_FOUND;\r
172 }\r
173\r
174 //\r
175 // Copy the data to user's buffer\r
176 //\r
177 Len = SIZEOF_NIC_IP4_CONFIG_INFO (Config);\r
178\r
179 if ((*ConfigLen < Len) || (NicConfig == NULL)) {\r
180 Status = EFI_BUFFER_TOO_SMALL;\r
181 } else {\r
182 Status = EFI_SUCCESS;\r
e48e37fc 183 CopyMem (NicConfig, Config, Len);\r
7659d0c9 184 Ip4ConfigFixRouteTablePointer (&NicConfig->Ip4Info);\r
b2570da8 185 }\r
186\r
187 *ConfigLen = Len;\r
188\r
e48e37fc 189 gBS->FreePool (Config);\r
b2570da8 190 return Status;\r
191}\r
192\r
193\r
194/**\r
195 Set the IP configure parameters for this NIC. If Reconfig is TRUE,\r
196 the IP driver will be informed to discard current auto configure\r
197 parameter and restart the auto configuration process. If current\r
198 there is a pending auto configuration, EFI_ALREADY_STARTED is\r
199 returned. You can only change the configure setting when either\r
200 the configure has finished or not started yet. If NicConfig, the\r
201 NIC's configure parameter is removed from the variable.\r
202\r
203 @param This The NIC IP4 CONFIG protocol\r
204 @param NicConfig The new NIC IP4 configure parameter\r
205 @param Reconfig Inform the IP4 driver to restart the auto\r
206 configuration\r
207\r
208 @retval EFI_INVALID_PARAMETER This is NULL or the configure parameter is\r
209 invalid.\r
210 @retval EFI_ALREADY_STARTED There is a pending auto configuration.\r
211 @retval EFI_NOT_FOUND No auto configure parameter is found\r
212\r
213**/\r
214EFI_STATUS\r
215EFIAPI\r
216EfiNicIp4ConfigSetInfo (\r
217 IN EFI_NIC_IP4_CONFIG_PROTOCOL *This,\r
218 IN NIC_IP4_CONFIG_INFO *NicConfig, OPTIONAL\r
219 IN BOOLEAN Reconfig\r
220 )\r
221{\r
222 IP4_CONFIG_INSTANCE *Instance;\r
223 IP4_CONFIG_VARIABLE *Variable;\r
224 IP4_CONFIG_VARIABLE *NewVariable;\r
225 EFI_STATUS Status;\r
226\r
227 //\r
228 // Validate the parameters\r
229 //\r
230 if (This == NULL) {\r
231 return EFI_INVALID_PARAMETER;\r
232 }\r
233\r
234 Instance = IP4_CONFIG_INSTANCE_FROM_NIC_IP4CONFIG (This);\r
235\r
236 if ((NicConfig != NULL) && (!Ip4ConfigIsValid (NicConfig) ||\r
237 !NIC_ADDR_EQUAL (&NicConfig->NicAddr, &Instance->NicAddr))) {\r
238 return EFI_INVALID_PARAMETER;\r
239 }\r
240\r
241 if (Instance->State == IP4_CONFIG_STATE_STARTED) {\r
242 return EFI_ALREADY_STARTED;\r
243 }\r
244\r
245 //\r
246 // Update the parameter in the configure variable\r
247 //\r
248 Variable = Ip4ConfigReadVariable ();\r
249\r
250 if ((Variable == NULL) && (NicConfig == NULL)) {\r
251 return EFI_NOT_FOUND;\r
252 }\r
253\r
254 NewVariable = Ip4ConfigModifyVariable (Variable, &Instance->NicAddr, NicConfig);\r
255 Status = Ip4ConfigWriteVariable (NewVariable);\r
256\r
257 if (NewVariable != NULL) {\r
e48e37fc 258 gBS->FreePool (NewVariable);\r
b2570da8 259 }\r
260\r
261 //\r
262 // Variable is NULL when saving the first configure parameter\r
263 //\r
264 if (Variable != NULL) {\r
e48e37fc 265 gBS->FreePool (Variable);\r
b2570da8 266 }\r
267\r
268 if (EFI_ERROR (Status)) {\r
269 return Status;\r
270 }\r
271\r
272 //\r
273 // Signal the IP4 to run the auto configuration again\r
274 //\r
275 if (Reconfig && (Instance->ReconfigEvent != NULL)) {\r
276 Status = gBS->SignalEvent (Instance->ReconfigEvent);\r
7659d0c9 277 NetLibDispatchDpc ();\r
b2570da8 278 }\r
279\r
280 return Status;\r
281}\r
282\r
283\r
284/**\r
402fa70f 285 Starts running the configuration policy for the EFI IPv4 Protocol driver.\r
286 \r
287 The Start() function is called to determine and to begin the platform \r
288 configuration policy by the EFI IPv4 Protocol driver. This determination may \r
289 be as simple as returning EFI_UNSUPPORTED if there is no EFI IPv4 Protocol \r
290 driver configuration policy. It may be as involved as loading some defaults \r
291 from nonvolatile storage, downloading dynamic data from a DHCP server, and \r
292 checking permissions with a site policy server.\r
293 Starting the configuration policy is just the beginning. It may finish almost \r
294 instantly or it may take several minutes before it fails to retrieve configuration \r
295 information from one or more servers. Once the policy is started, drivers \r
296 should use the DoneEvent parameter to determine when the configuration policy \r
297 has completed. EFI_IP4_CONFIG_PROTOCOL.GetData() must then be called to \r
298 determine if the configuration succeeded or failed.\r
299 Until the configuration completes successfully, EFI IPv4 Protocol driver instances \r
300 that are attempting to use default configurations must return EFI_NO_MAPPING.\r
301 Once the configuration is complete, the EFI IPv4 Configuration Protocol driver \r
302 signals DoneEvent. The configuration may need to be updated in the future, \r
303 however; in this case, the EFI IPv4 Configuration Protocol driver must signal \r
304 ReconfigEvent, and all EFI IPv4 Protocol driver instances that are using default \r
305 configurations must return EFI_NO_MAPPING until the configuration policy has \r
306 been rerun.\r
307\r
308 @param This Pointer to the EFI_IP4_CONFIG_PROTOCOL instance.\r
309 @param DoneEvent Event that will be signaled when the EFI IPv4 \r
310 Protocol driver configuration policy completes \r
311 execution. This event must be of type EVT_NOTIFY_SIGNAL.\r
312 @param ReconfigEvent Event that will be signaled when the EFI IPv4 \r
313 Protocol driver configuration needs to be updated. \r
314 This event must be of type EVT_NOTIFY_SIGNAL.\r
315 \r
316 @retval EFI_SUCCESS The configuration policy for the EFI IPv4 Protocol \r
317 driver is now running.\r
318 @retval EFI_INVALID_PARAMETER One or more of the following parameters is NULL:\r
319 This\r
320 DoneEvent\r
321 ReconfigEvent\r
322 @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.\r
323 @retval EFI_ALREADY_STARTED The configuration policy for the EFI IPv4 Protocol \r
324 driver was already started.\r
325 @retval EFI_DEVICE_ERROR An unexpected system error or network error occurred.\r
326 @retval EFI_UNSUPPORTED This interface does not support the EFI IPv4 Protocol \r
327 driver configuration.\r
b2570da8 328\r
329**/\r
330EFI_STATUS\r
331EFIAPI\r
332EfiIp4ConfigStart (\r
333 IN EFI_IP4_CONFIG_PROTOCOL *This,\r
334 IN EFI_EVENT DoneEvent,\r
335 IN EFI_EVENT ReconfigEvent\r
336 )\r
337{\r
338 IP4_CONFIG_INSTANCE *Instance;\r
339 EFI_DHCP4_PROTOCOL *Dhcp4;\r
340 EFI_DHCP4_MODE_DATA Dhcp4Mode;\r
341 EFI_DHCP4_PACKET_OPTION *OptionList[1];\r
342 IP4_CONFIG_DHCP4_OPTION ParaList;\r
343 EFI_STATUS Status;\r
344 UINT32 Source;\r
345 EFI_TPL OldTpl;\r
346\r
347 if ((This == NULL) || (DoneEvent == NULL) || (ReconfigEvent == NULL)) {\r
348 return EFI_INVALID_PARAMETER;\r
349 }\r
350\r
351 Instance = IP4_CONFIG_INSTANCE_FROM_IP4CONFIG (This);\r
352\r
e48e37fc 353 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
b2570da8 354\r
355 if (Instance->State != IP4_CONFIG_STATE_IDLE) {\r
356 Status = EFI_ALREADY_STARTED;\r
357\r
358 goto ON_EXIT;\r
359 }\r
360\r
361 Instance->DoneEvent = DoneEvent;\r
362 Instance->ReconfigEvent = ReconfigEvent;\r
363\r
364 Instance->NicConfig = Ip4ConfigGetNicInfo (&Instance->NicAddr);\r
365\r
366 if (Instance->NicConfig == NULL) {\r
367 Source = IP4_CONFIG_SOURCE_DHCP;\r
368 } else {\r
369 Source = Instance->NicConfig->Source;\r
370 }\r
371\r
372 //\r
373 // If the source is static, the auto configuration is done.\r
374 // return now.\r
375 //\r
376 if (Source == IP4_CONFIG_SOURCE_STATIC) {\r
377 Instance->State = IP4_CONFIG_STATE_CONFIGURED;\r
378 Instance->Result = EFI_SUCCESS;\r
379\r
380 gBS->SignalEvent (Instance->DoneEvent);\r
381 Status = EFI_SUCCESS;\r
382 goto ON_EXIT;\r
383 }\r
384\r
385 //\r
386 // Start the dhcp process\r
387 //\r
388 ASSERT ((Source == IP4_CONFIG_SOURCE_DHCP) && (Instance->Dhcp4 == NULL));\r
389\r
390 Status = NetLibCreateServiceChild (\r
391 Instance->Controller,\r
392 Instance->Image,\r
393 &gEfiDhcp4ServiceBindingProtocolGuid,\r
394 &Instance->Dhcp4Handle\r
395 );\r
396\r
397 if (EFI_ERROR (Status)) {\r
398 goto ON_ERROR;\r
399 }\r
400\r
401 Status = gBS->OpenProtocol (\r
402 Instance->Dhcp4Handle,\r
403 &gEfiDhcp4ProtocolGuid,\r
404 (VOID **) &Instance->Dhcp4,\r
405 Instance->Image,\r
406 Instance->Controller,\r
407 EFI_OPEN_PROTOCOL_BY_DRIVER\r
408 );\r
409\r
410 if (EFI_ERROR (Status)) {\r
411 goto ON_ERROR;\r
412 }\r
413\r
414 //\r
415 // Check the current DHCP status, if the DHCP process has\r
416 // already finished, return now.\r
417 //\r
418 Dhcp4 = Instance->Dhcp4;\r
419 Status = Dhcp4->GetModeData (Dhcp4, &Dhcp4Mode);\r
420\r
421 if (EFI_ERROR (Status)) {\r
422 goto ON_ERROR;\r
423 }\r
424\r
425 if (Dhcp4Mode.State == Dhcp4Bound) {\r
426 Ip4ConfigOnDhcp4Complete (NULL, Instance);\r
427\r
428 goto ON_EXIT;\r
429 }\r
430\r
431 //\r
432 // Try to start the DHCP process. Use most of the current\r
433 // DHCP configuration to avoid problems if some DHCP client\r
434 // yields the control of this DHCP service to us.\r
435 //\r
436 ParaList.Head.OpCode = DHCP_TAG_PARA_LIST;\r
437 ParaList.Head.Length = 2;\r
438 ParaList.Head.Data[0] = DHCP_TAG_NETMASK;\r
439 ParaList.Route = DHCP_TAG_ROUTER;\r
440 OptionList[0] = &ParaList.Head;\r
441 Dhcp4Mode.ConfigData.OptionCount = 1;\r
442 Dhcp4Mode.ConfigData.OptionList = OptionList;\r
443\r
444 Status = Dhcp4->Configure (Dhcp4, &Dhcp4Mode.ConfigData);\r
445\r
446 if (EFI_ERROR (Status)) {\r
447 goto ON_ERROR;\r
448 }\r
449\r
450 //\r
451 // Start the DHCP process\r
452 //\r
453 Status = gBS->CreateEvent (\r
454 EVT_NOTIFY_SIGNAL,\r
e48e37fc 455 TPL_CALLBACK,\r
b2570da8 456 Ip4ConfigOnDhcp4Complete,\r
457 Instance,\r
458 &Instance->Dhcp4Event\r
459 );\r
460\r
461 if (EFI_ERROR (Status)) {\r
462 goto ON_ERROR;\r
463 }\r
464\r
465 Status = Dhcp4->Start (Dhcp4, Instance->Dhcp4Event);\r
466\r
467 if (EFI_ERROR (Status)) {\r
468 goto ON_ERROR;\r
469 }\r
470\r
471 Instance->State = IP4_CONFIG_STATE_STARTED;\r
472 Instance->Result = EFI_NOT_READY;\r
473\r
474ON_ERROR:\r
475 if (EFI_ERROR (Status)) {\r
476 Ip4ConfigCleanConfig (Instance);\r
477 }\r
478\r
479ON_EXIT:\r
e48e37fc 480 gBS->RestoreTPL (OldTpl);\r
b2570da8 481\r
7659d0c9 482 NetLibDispatchDpc ();\r
483\r
b2570da8 484 return Status;\r
485}\r
486\r
487\r
488/**\r
402fa70f 489 Stops running the configuration policy for the EFI IPv4 Protocol driver.\r
490 \r
491 The Stop() function stops the configuration policy for the EFI IPv4 Protocol driver. \r
492 All configuration data will be lost after calling Stop().\r
b2570da8 493\r
402fa70f 494 @param This Pointer to the EFI_IP4_CONFIG_PROTOCOL instance.\r
b2570da8 495\r
402fa70f 496 @retval EFI_SUCCESS The configuration policy for the EFI IPv4 Protocol \r
497 driver has been stopped.\r
b2570da8 498 @retval EFI_INVALID_PARAMETER This is NULL.\r
402fa70f 499 @retval EFI_NOT_STARTED The configuration policy for the EFI IPv4 Protocol \r
500 driver was not started.\r
501 \r
b2570da8 502**/\r
503EFI_STATUS\r
504EFIAPI\r
505EfiIp4ConfigStop (\r
506 IN EFI_IP4_CONFIG_PROTOCOL *This\r
507 )\r
508{\r
509 IP4_CONFIG_INSTANCE *Instance;\r
510 EFI_STATUS Status;\r
511 EFI_TPL OldTpl;\r
512\r
513 if (This == NULL) {\r
514 return EFI_INVALID_PARAMETER;\r
515 }\r
516\r
517 Instance = IP4_CONFIG_INSTANCE_FROM_IP4CONFIG (This);\r
518\r
519 Status = EFI_SUCCESS;\r
e48e37fc 520 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
b2570da8 521\r
522 if (Instance->State == IP4_CONFIG_STATE_IDLE) {\r
523 Status = EFI_NOT_STARTED;\r
524 goto ON_EXIT;\r
525 }\r
526\r
527 //\r
528 // Release all the configure parameters. Don't signal the user\r
529 // event. The user wants to abort the configuration, this isn't\r
530 // the configuration done or reconfiguration.\r
531 //\r
532 Ip4ConfigCleanConfig (Instance);\r
533\r
534ON_EXIT:\r
e48e37fc 535 gBS->RestoreTPL (OldTpl);\r
b2570da8 536\r
537 return Status;\r
538}\r
539\r
540\r
541/**\r
402fa70f 542 Returns the default configuration data (if any) for the EFI IPv4 Protocol driver.\r
543\r
544 The GetData() function returns the current configuration data for the EFI IPv4 \r
545 Protocol driver after the configuration policy has completed.\r
546 \r
547 @param This Pointer to the EFI_IP4_CONFIG_PROTOCOL instance.\r
548 @param ConfigDataSize On input, the size of the ConfigData buffer. \r
549 On output, the count of bytes that were written \r
550 into the ConfigData buffer.\r
551 @param ConfigData Pointer to the EFI IPv4 Configuration Protocol \r
552 driver configuration data structure. \r
553 Type EFI_IP4_IPCONFIG_DATA is defined in \r
554 "Related Definitions" below.\r
555\r
556 @retval EFI_SUCCESS The EFI IPv4 Protocol driver configuration has been returned.\r
557 @retval EFI_INVALID_PARAMETER This is NULL.\r
558 @retval EFI_NOT_STARTED The configuration policy for the EFI IPv4 Protocol \r
559 driver is not running.\r
560 @retval EFI_NOT_READY EFI IPv4 Protocol driver configuration is still running.\r
561 @retval EFI_ABORTED EFI IPv4 Protocol driver configuration could not complete.\r
562 @retval EFI_BUFFER_TOO_SMALL *ConfigDataSize is smaller than the configuration \r
563 data buffer or ConfigData is NULL.\r
b2570da8 564\r
565**/\r
566EFI_STATUS\r
567EFIAPI\r
568EfiIp4ConfigGetData (\r
569 IN EFI_IP4_CONFIG_PROTOCOL *This,\r
570 IN OUT UINTN *ConfigDataSize,\r
571 OUT EFI_IP4_IPCONFIG_DATA *ConfigData OPTIONAL\r
572 )\r
573{\r
574 IP4_CONFIG_INSTANCE *Instance;\r
575 NIC_IP4_CONFIG_INFO *NicConfig;\r
576 EFI_STATUS Status;\r
577 EFI_TPL OldTpl;\r
578 UINTN Len;\r
579\r
580 if ((This == NULL) || (ConfigDataSize == NULL)) {\r
581 return EFI_INVALID_PARAMETER;\r
582 }\r
583\r
584 Instance = IP4_CONFIG_INSTANCE_FROM_IP4CONFIG (This);\r
585\r
586 Status = EFI_SUCCESS;\r
e48e37fc 587 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
b2570da8 588\r
589 if (Instance->State == IP4_CONFIG_STATE_IDLE) {\r
590 Status = EFI_NOT_STARTED;\r
591 } else if (Instance->State == IP4_CONFIG_STATE_STARTED) {\r
592 Status = EFI_NOT_READY;\r
593 }\r
594\r
595 if (EFI_ERROR (Status)) {\r
596 goto ON_EXIT;\r
597 }\r
598\r
599 //\r
600 // Copy the configure data if auto configuration succeeds.\r
601 //\r
602 Status = Instance->Result;\r
603\r
604 if (Status == EFI_SUCCESS) {\r
605 ASSERT (Instance->NicConfig != NULL);\r
606\r
607 NicConfig = Instance->NicConfig;\r
608 Len = SIZEOF_IP4_CONFIG_INFO (&NicConfig->Ip4Info);\r
609\r
610 if ((*ConfigDataSize < Len) || (ConfigData == NULL)) {\r
611 Status = EFI_BUFFER_TOO_SMALL;\r
612 } else {\r
e48e37fc 613 CopyMem (ConfigData, &NicConfig->Ip4Info, Len);\r
7659d0c9 614 Ip4ConfigFixRouteTablePointer (ConfigData);\r
b2570da8 615 }\r
616\r
617 *ConfigDataSize = Len;\r
618 }\r
619\r
620ON_EXIT:\r
e48e37fc 621 gBS->RestoreTPL (OldTpl);\r
b2570da8 622\r
623 return Status;\r
624}\r
625\r
626\r
627/**\r
628 Callback function when DHCP process finished. It will save the\r
629 retrieved IP configure parameter from DHCP to the NVRam.\r
630\r
631 @param Event The callback event\r
632 @param Context Opaque context to the callback\r
633\r
634 @return None\r
635\r
636**/\r
637VOID\r
638EFIAPI\r
639Ip4ConfigOnDhcp4Complete (\r
640 IN EFI_EVENT Event,\r
641 IN VOID *Context\r
642 )\r
643{\r
644 IP4_CONFIG_INSTANCE *Instance;\r
645 EFI_DHCP4_MODE_DATA Dhcp4Mode;\r
646 EFI_IP4_IPCONFIG_DATA *Ip4Config;\r
647 EFI_STATUS Status;\r
648 BOOLEAN Perment;\r
649 IP4_ADDR Subnet;\r
772db4bb 650 IP4_ADDR Ip1;\r
651 IP4_ADDR Ip2;\r
b2570da8 652\r
653 Instance = (IP4_CONFIG_INSTANCE *) Context;\r
654 ASSERT (Instance->Dhcp4 != NULL);\r
655\r
656 Instance->State = IP4_CONFIG_STATE_CONFIGURED;\r
657 Instance->Result = EFI_TIMEOUT;\r
658\r
659 //\r
660 // Get the DHCP retrieved parameters\r
661 //\r
662 Status = Instance->Dhcp4->GetModeData (Instance->Dhcp4, &Dhcp4Mode);\r
663\r
664 if (EFI_ERROR (Status)) {\r
665 goto ON_EXIT;\r
666 }\r
667\r
668 if (Dhcp4Mode.State == Dhcp4Bound) {\r
669 //\r
670 // Save the new configuration retrieved by DHCP both in\r
671 // the instance and to NVRam. So, both the IP4 driver and\r
672 // other user can get that address.\r
673 //\r
674 Perment = FALSE;\r
675\r
676 if (Instance->NicConfig != NULL) {\r
677 ASSERT (Instance->NicConfig->Source == IP4_CONFIG_SOURCE_DHCP);\r
678 Perment = Instance->NicConfig->Perment;\r
e48e37fc 679 gBS->FreePool (Instance->NicConfig);\r
b2570da8 680 }\r
681\r
e48e37fc 682 Instance->NicConfig = AllocatePool (sizeof (NIC_IP4_CONFIG_INFO) + 2* sizeof (EFI_IP4_ROUTE_TABLE));\r
b2570da8 683\r
684 if (Instance->NicConfig == NULL) {\r
685 Instance->Result = EFI_OUT_OF_RESOURCES;\r
686 goto ON_EXIT;\r
687 }\r
688\r
305a1279 689 Instance->NicConfig->Ip4Info.RouteTable = (EFI_IP4_ROUTE_TABLE *) (Instance->NicConfig + 1);\r
690\r
687a2e5f 691 CopyMem (&Instance->NicConfig->NicAddr, &Instance->NicAddr, sizeof (Instance->NicConfig->NicAddr));\r
b2570da8 692 Instance->NicConfig->Source = IP4_CONFIG_SOURCE_DHCP;\r
693 Instance->NicConfig->Perment = Perment;\r
694\r
695 Ip4Config = &Instance->NicConfig->Ip4Info;\r
696 Ip4Config->StationAddress = Dhcp4Mode.ClientAddress;\r
697 Ip4Config->SubnetMask = Dhcp4Mode.SubnetMask;\r
698\r
699 //\r
700 // Create a route for the connected network\r
701 //\r
702 Ip4Config->RouteTableSize = 1;\r
703\r
e48e37fc 704 CopyMem (&Ip1, &Dhcp4Mode.ClientAddress, sizeof (IP4_ADDR));\r
705 CopyMem (&Ip2, &Dhcp4Mode.SubnetMask, sizeof (IP4_ADDR));\r
305a1279 706\r
772db4bb 707 Subnet = Ip1 & Ip2;\r
b2570da8 708\r
e48e37fc 709 CopyMem (&Ip4Config->RouteTable[0].SubnetAddress, &Subnet, sizeof (EFI_IPv4_ADDRESS));\r
710 CopyMem (&Ip4Config->RouteTable[0].SubnetMask, &Dhcp4Mode.SubnetMask, sizeof (EFI_IPv4_ADDRESS));\r
711 ZeroMem (&Ip4Config->RouteTable[0].GatewayAddress, sizeof (EFI_IPv4_ADDRESS));\r
b2570da8 712\r
713 //\r
714 // Create a route if there is a default router.\r
715 //\r
84b5c78e 716 if (!EFI_IP4_EQUAL (&Dhcp4Mode.RouterAddress, &mZeroIp4Addr)) {\r
772db4bb 717 Ip4Config->RouteTableSize = 2;\r
718\r
e48e37fc 719 ZeroMem (&Ip4Config->RouteTable[1].SubnetAddress, sizeof (EFI_IPv4_ADDRESS));\r
720 ZeroMem (&Ip4Config->RouteTable[1].SubnetMask, sizeof (EFI_IPv4_ADDRESS));\r
721 CopyMem (&Ip4Config->RouteTable[1].GatewayAddress, &Dhcp4Mode.RouterAddress, sizeof (EFI_IPv4_ADDRESS));\r
b2570da8 722 }\r
723\r
724 Instance->Result = EFI_SUCCESS;\r
725\r
726 //\r
727 // ignore the return status of EfiNicIp4ConfigSetInfo. Network\r
728 // stack can operate even that failed.\r
729 //\r
730 EfiNicIp4ConfigSetInfo (&Instance->NicIp4Protocol, Instance->NicConfig, FALSE);\r
731 }\r
732\r
733ON_EXIT:\r
734 gBS->SignalEvent (Instance->DoneEvent);\r
735 Ip4ConfigCleanDhcp4 (Instance);\r
7659d0c9 736\r
737 NetLibDispatchDpc ();\r
738\r
b2570da8 739 return ;\r
740}\r
741\r
742\r
743/**\r
744 Release all the DHCP related resources.\r
745\r
746 @param This The IP4 configure instance\r
747\r
748 @return None\r
749\r
750**/\r
751VOID\r
752Ip4ConfigCleanDhcp4 (\r
753 IN IP4_CONFIG_INSTANCE *This\r
754 )\r
755{\r
756 if (This->Dhcp4 != NULL) {\r
757 This->Dhcp4->Stop (This->Dhcp4);\r
758\r
759 gBS->CloseProtocol (\r
760 This->Dhcp4Handle,\r
761 &gEfiDhcp4ProtocolGuid,\r
762 This->Image,\r
763 This->Controller\r
764 );\r
765\r
766 This->Dhcp4 = NULL;\r
767 }\r
768\r
769 if (This->Dhcp4Handle != NULL) {\r
770 NetLibDestroyServiceChild (\r
771 This->Controller,\r
772 This->Image,\r
773 &gEfiDhcp4ServiceBindingProtocolGuid,\r
774 This->Dhcp4Handle\r
775 );\r
776\r
777 This->Dhcp4Handle = NULL;\r
778 }\r
779\r
780 if (This->Dhcp4Event == NULL) {\r
781 gBS->CloseEvent (This->Dhcp4Event);\r
782 This->Dhcp4Event = NULL;\r
783 }\r
784}\r
785\r
786\r
787/**\r
7bce0c5a 788 Clean up all the configuration parameters.\r
b2570da8 789\r
790 @param Instance The IP4 configure instance\r
791\r
792 @return None\r
793\r
794**/\r
795VOID\r
796Ip4ConfigCleanConfig (\r
797 IN IP4_CONFIG_INSTANCE *Instance\r
798 )\r
799{\r
800 if (Instance->NicConfig != NULL) {\r
e48e37fc 801 gBS->FreePool (Instance->NicConfig);\r
b2570da8 802 Instance->NicConfig = NULL;\r
803 }\r
804\r
805 Instance->State = IP4_CONFIG_STATE_IDLE;\r
806 Instance->DoneEvent = NULL;\r
807 Instance->ReconfigEvent = NULL;\r
808\r
809 Ip4ConfigCleanDhcp4 (Instance);\r
810}\r
811\r
812EFI_IP4_CONFIG_PROTOCOL mIp4ConfigProtocolTemplate = {\r
813 EfiIp4ConfigStart,\r
814 EfiIp4ConfigStop,\r
815 EfiIp4ConfigGetData\r
816};\r
817\r
818EFI_NIC_IP4_CONFIG_PROTOCOL mNicIp4ConfigProtocolTemplate = {\r
819 EfiNicIp4ConfigGetName,\r
820 EfiNicIp4ConfigGetInfo,\r
821 EfiNicIp4ConfigSetInfo\r
822};\r