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