31d9e8b9034ae0347e87a704de3f7dfba4e80fb1
[people/mcb30/edk2.git] / edk2 / MdeModulePkg / Universal / Network / Ip4ConfigDxe / Ip4Config.c
1 /** @file\r
2 \r
3 Copyright (c) 2006 - 2007, 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     NetCopyMem (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     NetFreePool (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       NetFreePool (NewVariable);\r
122     };\r
123 \r
124     NetFreePool (Config);\r
125     Config = NULL;\r
126   }\r
127 \r
128   NetFreePool (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     NetCopyMem (NicConfig, Config, Len);\r
183   }\r
184 \r
185   *ConfigLen = Len;\r
186 \r
187   NetFreePool (Config);\r
188   return Status;\r
189 }\r
190 \r
191 \r
192 /**\r
193   Set the IP configure parameters for this NIC. If Reconfig is TRUE,\r
194   the IP driver will be informed to discard current auto configure\r
195   parameter and restart the auto configuration process. If current\r
196   there is a pending auto configuration, EFI_ALREADY_STARTED is\r
197   returned. You can only change the configure setting when either\r
198   the configure has finished or not started yet. If NicConfig, the\r
199   NIC's configure parameter is removed from the variable.\r
200 \r
201   @param  This                   The NIC IP4 CONFIG protocol\r
202   @param  NicConfig              The new NIC IP4 configure parameter\r
203   @param  Reconfig               Inform the IP4 driver to restart the auto\r
204                                  configuration\r
205 \r
206   @retval EFI_INVALID_PARAMETER  This is NULL or the configure parameter is\r
207                                  invalid.\r
208   @retval EFI_ALREADY_STARTED    There is a pending auto configuration.\r
209   @retval EFI_NOT_FOUND          No auto configure parameter is found\r
210 \r
211 **/\r
212 EFI_STATUS\r
213 EFIAPI\r
214 EfiNicIp4ConfigSetInfo (\r
215   IN EFI_NIC_IP4_CONFIG_PROTOCOL  *This,\r
216   IN NIC_IP4_CONFIG_INFO          *NicConfig,     OPTIONAL\r
217   IN BOOLEAN                      Reconfig\r
218   )\r
219 {\r
220   IP4_CONFIG_INSTANCE *Instance;\r
221   IP4_CONFIG_VARIABLE *Variable;\r
222   IP4_CONFIG_VARIABLE *NewVariable;\r
223   EFI_STATUS          Status;\r
224 \r
225   //\r
226   // Validate the parameters\r
227   //\r
228   if (This == NULL) {\r
229     return EFI_INVALID_PARAMETER;\r
230   }\r
231 \r
232   Instance = IP4_CONFIG_INSTANCE_FROM_NIC_IP4CONFIG (This);\r
233 \r
234   if ((NicConfig != NULL) && (!Ip4ConfigIsValid (NicConfig) ||\r
235       !NIC_ADDR_EQUAL (&NicConfig->NicAddr, &Instance->NicAddr))) {\r
236     return EFI_INVALID_PARAMETER;\r
237   }\r
238 \r
239   if (Instance->State == IP4_CONFIG_STATE_STARTED) {\r
240     return EFI_ALREADY_STARTED;\r
241   }\r
242 \r
243   //\r
244   // Update the parameter in the configure variable\r
245   //\r
246   Variable = Ip4ConfigReadVariable ();\r
247 \r
248   if ((Variable == NULL) && (NicConfig == NULL)) {\r
249     return EFI_NOT_FOUND;\r
250   }\r
251 \r
252   NewVariable = Ip4ConfigModifyVariable (Variable, &Instance->NicAddr, NicConfig);\r
253   Status      = Ip4ConfigWriteVariable (NewVariable);\r
254 \r
255   if (NewVariable != NULL) {\r
256     NetFreePool (NewVariable);\r
257   }\r
258 \r
259   //\r
260   // Variable is NULL when saving the first configure parameter\r
261   //\r
262   if (Variable != NULL) {\r
263     NetFreePool (Variable);\r
264   }\r
265 \r
266   if (EFI_ERROR (Status)) {\r
267     return Status;\r
268   }\r
269 \r
270   //\r
271   // Signal the IP4 to run the auto configuration again\r
272   //\r
273   if (Reconfig && (Instance->ReconfigEvent != NULL)) {\r
274     Status = gBS->SignalEvent (Instance->ReconfigEvent);\r
275   }\r
276 \r
277   return Status;\r
278 }\r
279 \r
280 \r
281 /**\r
282   Start the auto configuration process.\r
283 \r
284   @param  This                   The IP4 configure protocol\r
285   @param  DoneEvent              The event to signal when auto configure is done\r
286   @param  ReconfigEvent          The event to signal when reconfigure is necessary.\r
287 \r
288   @retval EFI_INVALID_PARAMETER  One of the function parameters is NULL.\r
289   @retval EFI_ALREADY_STARTED    The auto configuration has already started.\r
290   @retval EFI_SUCCESS            The auto configure is successfully started.\r
291 \r
292 **/\r
293 EFI_STATUS\r
294 EFIAPI\r
295 EfiIp4ConfigStart (\r
296   IN EFI_IP4_CONFIG_PROTOCOL  *This,\r
297   IN EFI_EVENT                DoneEvent,\r
298   IN EFI_EVENT                ReconfigEvent\r
299   )\r
300 {\r
301   IP4_CONFIG_INSTANCE       *Instance;\r
302   EFI_DHCP4_PROTOCOL        *Dhcp4;\r
303   EFI_DHCP4_MODE_DATA       Dhcp4Mode;\r
304   EFI_DHCP4_PACKET_OPTION   *OptionList[1];\r
305   IP4_CONFIG_DHCP4_OPTION   ParaList;\r
306   EFI_STATUS                Status;\r
307   UINT32                    Source;\r
308   EFI_TPL                   OldTpl;\r
309 \r
310   if ((This == NULL) || (DoneEvent == NULL) || (ReconfigEvent == NULL)) {\r
311     return EFI_INVALID_PARAMETER;\r
312   }\r
313 \r
314   Instance = IP4_CONFIG_INSTANCE_FROM_IP4CONFIG (This);\r
315 \r
316   OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);\r
317 \r
318   if (Instance->State != IP4_CONFIG_STATE_IDLE) {\r
319     Status = EFI_ALREADY_STARTED;\r
320 \r
321     goto ON_EXIT;\r
322   }\r
323 \r
324   Instance->DoneEvent     = DoneEvent;\r
325   Instance->ReconfigEvent = ReconfigEvent;\r
326 \r
327   Instance->NicConfig     = Ip4ConfigGetNicInfo (&Instance->NicAddr);\r
328 \r
329   if (Instance->NicConfig == NULL) {\r
330     Source = IP4_CONFIG_SOURCE_DHCP;\r
331   } else {\r
332     Source = Instance->NicConfig->Source;\r
333   }\r
334 \r
335   //\r
336   // If the source is static, the auto configuration is done.\r
337   // return now.\r
338   //\r
339   if (Source == IP4_CONFIG_SOURCE_STATIC) {\r
340     Instance->State  = IP4_CONFIG_STATE_CONFIGURED;\r
341     Instance->Result = EFI_SUCCESS;\r
342 \r
343     gBS->SignalEvent (Instance->DoneEvent);\r
344     Status = EFI_SUCCESS;\r
345     goto ON_EXIT;\r
346   }\r
347 \r
348   //\r
349   // Start the dhcp process\r
350   //\r
351   ASSERT ((Source == IP4_CONFIG_SOURCE_DHCP) && (Instance->Dhcp4 == NULL));\r
352 \r
353   Status = NetLibCreateServiceChild (\r
354              Instance->Controller,\r
355              Instance->Image,\r
356              &gEfiDhcp4ServiceBindingProtocolGuid,\r
357              &Instance->Dhcp4Handle\r
358              );\r
359 \r
360   if (EFI_ERROR (Status)) {\r
361     goto ON_ERROR;\r
362   }\r
363 \r
364   Status = gBS->OpenProtocol (\r
365                   Instance->Dhcp4Handle,\r
366                   &gEfiDhcp4ProtocolGuid,\r
367                   (VOID **) &Instance->Dhcp4,\r
368                   Instance->Image,\r
369                   Instance->Controller,\r
370                   EFI_OPEN_PROTOCOL_BY_DRIVER\r
371                   );\r
372 \r
373   if (EFI_ERROR (Status)) {\r
374     goto ON_ERROR;\r
375   }\r
376 \r
377   //\r
378   // Check the current DHCP status, if the DHCP process has\r
379   // already finished, return now.\r
380   //\r
381   Dhcp4  = Instance->Dhcp4;\r
382   Status = Dhcp4->GetModeData (Dhcp4, &Dhcp4Mode);\r
383 \r
384   if (EFI_ERROR (Status)) {\r
385     goto ON_ERROR;\r
386   }\r
387 \r
388   if (Dhcp4Mode.State == Dhcp4Bound) {\r
389     Ip4ConfigOnDhcp4Complete (NULL, Instance);\r
390 \r
391     goto ON_EXIT;\r
392   }\r
393 \r
394   //\r
395   // Try to start the DHCP process. Use most of the current\r
396   // DHCP configuration to avoid problems if some DHCP client\r
397   // yields the control of this DHCP service to us.\r
398   //\r
399   ParaList.Head.OpCode             = DHCP_TAG_PARA_LIST;\r
400   ParaList.Head.Length             = 2;\r
401   ParaList.Head.Data[0]            = DHCP_TAG_NETMASK;\r
402   ParaList.Route                   = DHCP_TAG_ROUTER;\r
403   OptionList[0]                    = &ParaList.Head;\r
404   Dhcp4Mode.ConfigData.OptionCount = 1;\r
405   Dhcp4Mode.ConfigData.OptionList  = OptionList;\r
406 \r
407   Status = Dhcp4->Configure (Dhcp4, &Dhcp4Mode.ConfigData);\r
408 \r
409   if (EFI_ERROR (Status)) {\r
410     goto ON_ERROR;\r
411   }\r
412 \r
413   //\r
414   // Start the DHCP process\r
415   //\r
416   Status = gBS->CreateEvent (\r
417                   EVT_NOTIFY_SIGNAL,\r
418                   NET_TPL_EVENT,\r
419                   Ip4ConfigOnDhcp4Complete,\r
420                   Instance,\r
421                   &Instance->Dhcp4Event\r
422                   );\r
423 \r
424   if (EFI_ERROR (Status)) {\r
425     goto ON_ERROR;\r
426   }\r
427 \r
428   Status = Dhcp4->Start (Dhcp4, Instance->Dhcp4Event);\r
429 \r
430   if (EFI_ERROR (Status)) {\r
431     goto ON_ERROR;\r
432   }\r
433 \r
434   Instance->State  = IP4_CONFIG_STATE_STARTED;\r
435   Instance->Result = EFI_NOT_READY;\r
436 \r
437 ON_ERROR:\r
438   if (EFI_ERROR (Status)) {\r
439     Ip4ConfigCleanConfig (Instance);\r
440   }\r
441 \r
442 ON_EXIT:\r
443   NET_RESTORE_TPL (OldTpl);\r
444 \r
445   return Status;\r
446 }\r
447 \r
448 \r
449 /**\r
450   Stop the current auto configuration\r
451 \r
452   @param  This                   The IP4 CONFIG protocol\r
453 \r
454   @retval EFI_INVALID_PARAMETER  This is NULL.\r
455   @retval EFI_NOT_STARTED        The auto configuration hasn't been started.\r
456   @retval EFI_SUCCESS            The auto configuration has been stopped.\r
457 \r
458 **/\r
459 EFI_STATUS\r
460 EFIAPI\r
461 EfiIp4ConfigStop (\r
462   IN EFI_IP4_CONFIG_PROTOCOL  *This\r
463   )\r
464 {\r
465   IP4_CONFIG_INSTANCE  *Instance;\r
466   EFI_STATUS           Status;\r
467   EFI_TPL              OldTpl;\r
468 \r
469   if (This == NULL) {\r
470     return EFI_INVALID_PARAMETER;\r
471   }\r
472 \r
473   Instance = IP4_CONFIG_INSTANCE_FROM_IP4CONFIG (This);\r
474 \r
475   Status = EFI_SUCCESS;\r
476   OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);\r
477 \r
478   if (Instance->State == IP4_CONFIG_STATE_IDLE) {\r
479     Status = EFI_NOT_STARTED;\r
480     goto ON_EXIT;\r
481   }\r
482 \r
483   //\r
484   // Release all the configure parameters. Don't signal the user\r
485   // event. The user wants to abort the configuration, this isn't\r
486   // the configuration done or reconfiguration.\r
487   //\r
488   Ip4ConfigCleanConfig (Instance);\r
489 \r
490 ON_EXIT:\r
491   NET_RESTORE_TPL (OldTpl);\r
492 \r
493   return Status;\r
494 }\r
495 \r
496 \r
497 /**\r
498   Get the current outcome of the auto configuration process\r
499 \r
500   @param  This                   The IP4 CONFIG protocol\r
501   @param  ConfigDataSize         The size of the configure data\r
502   @param  ConfigData             The buffer to save the configure data\r
503 \r
504   @retval EFI_INVALID_PARAMETER  This or ConfigDataSize is NULL\r
505   @retval EFI_BUFFER_TOO_SMALL   The buffer is too small. The needed size is\r
506                                  returned in the ConfigDataSize.\r
507   @retval EFI_SUCCESS            The configure data is put in the buffer\r
508 \r
509 **/\r
510 EFI_STATUS\r
511 EFIAPI\r
512 EfiIp4ConfigGetData (\r
513   IN  EFI_IP4_CONFIG_PROTOCOL *This,\r
514   IN  OUT  UINTN              *ConfigDataSize,\r
515   OUT EFI_IP4_IPCONFIG_DATA   *ConfigData           OPTIONAL\r
516   )\r
517 {\r
518   IP4_CONFIG_INSTANCE       *Instance;\r
519   NIC_IP4_CONFIG_INFO       *NicConfig;\r
520   EFI_STATUS                Status;\r
521   EFI_TPL                   OldTpl;\r
522   UINTN                     Len;\r
523 \r
524   if ((This == NULL) || (ConfigDataSize == NULL)) {\r
525     return EFI_INVALID_PARAMETER;\r
526   }\r
527 \r
528   Instance  = IP4_CONFIG_INSTANCE_FROM_IP4CONFIG (This);\r
529 \r
530   Status = EFI_SUCCESS;\r
531   OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);\r
532 \r
533   if (Instance->State == IP4_CONFIG_STATE_IDLE) {\r
534     Status = EFI_NOT_STARTED;\r
535   } else if (Instance->State == IP4_CONFIG_STATE_STARTED) {\r
536     Status = EFI_NOT_READY;\r
537   }\r
538 \r
539   if (EFI_ERROR (Status)) {\r
540     goto ON_EXIT;\r
541   }\r
542 \r
543   //\r
544   // Copy the configure data if auto configuration succeeds.\r
545   //\r
546   Status = Instance->Result;\r
547 \r
548   if (Status == EFI_SUCCESS) {\r
549     ASSERT (Instance->NicConfig != NULL);\r
550 \r
551     NicConfig = Instance->NicConfig;\r
552     Len       = SIZEOF_IP4_CONFIG_INFO (&NicConfig->Ip4Info);\r
553 \r
554     if ((*ConfigDataSize < Len) || (ConfigData == NULL)) {\r
555       Status = EFI_BUFFER_TOO_SMALL;\r
556     } else {\r
557       NetCopyMem (ConfigData, &NicConfig->Ip4Info, Len);\r
558     }\r
559 \r
560     *ConfigDataSize = Len;\r
561   }\r
562 \r
563 ON_EXIT:\r
564   NET_RESTORE_TPL (OldTpl);\r
565 \r
566   return Status;\r
567 }\r
568 \r
569 \r
570 /**\r
571   Callback function when DHCP process finished. It will save the\r
572   retrieved IP configure parameter from DHCP to the NVRam.\r
573 \r
574   @param  Event                  The callback event\r
575   @param  Context                Opaque context to the callback\r
576 \r
577   @return None\r
578 \r
579 **/\r
580 VOID\r
581 EFIAPI\r
582 Ip4ConfigOnDhcp4Complete (\r
583   IN EFI_EVENT              Event,\r
584   IN VOID                   *Context\r
585   )\r
586 {\r
587   IP4_CONFIG_INSTANCE       *Instance;\r
588   EFI_DHCP4_MODE_DATA       Dhcp4Mode;\r
589   EFI_IP4_IPCONFIG_DATA     *Ip4Config;\r
590   EFI_STATUS                Status;\r
591   BOOLEAN                   Perment;\r
592   IP4_ADDR                  Subnet;\r
593   IP4_ADDR                  Ip1;\r
594   IP4_ADDR                  Ip2;\r
595 \r
596   Instance = (IP4_CONFIG_INSTANCE *) Context;\r
597   ASSERT (Instance->Dhcp4 != NULL);\r
598 \r
599   Instance->State   = IP4_CONFIG_STATE_CONFIGURED;\r
600   Instance->Result  = EFI_TIMEOUT;\r
601 \r
602   //\r
603   // Get the DHCP retrieved parameters\r
604   //\r
605   Status = Instance->Dhcp4->GetModeData (Instance->Dhcp4, &Dhcp4Mode);\r
606 \r
607   if (EFI_ERROR (Status)) {\r
608     goto ON_EXIT;\r
609   }\r
610 \r
611   if (Dhcp4Mode.State == Dhcp4Bound) {\r
612     //\r
613     // Save the new configuration retrieved by DHCP both in\r
614     // the instance and to NVRam. So, both the IP4 driver and\r
615     // other user can get that address.\r
616     //\r
617     Perment = FALSE;\r
618 \r
619     if (Instance->NicConfig != NULL) {\r
620       ASSERT (Instance->NicConfig->Source == IP4_CONFIG_SOURCE_DHCP);\r
621       Perment = Instance->NicConfig->Perment;\r
622       NetFreePool (Instance->NicConfig);\r
623     }\r
624 \r
625     Instance->NicConfig = NetAllocatePool (sizeof (NIC_IP4_CONFIG_INFO) +\r
626                                            sizeof (EFI_IP4_ROUTE_TABLE));\r
627 \r
628     if (Instance->NicConfig == NULL) {\r
629       Instance->Result = EFI_OUT_OF_RESOURCES;\r
630       goto ON_EXIT;\r
631     }\r
632 \r
633     CopyMem (&Instance->NicConfig->NicAddr, &Instance->NicAddr, sizeof (Instance->NicConfig->NicAddr));\r
634     Instance->NicConfig->Source  = IP4_CONFIG_SOURCE_DHCP;\r
635     Instance->NicConfig->Perment = Perment;\r
636 \r
637     Ip4Config                    = &Instance->NicConfig->Ip4Info;\r
638     Ip4Config->StationAddress    = Dhcp4Mode.ClientAddress;\r
639     Ip4Config->SubnetMask        = Dhcp4Mode.SubnetMask;\r
640 \r
641     //\r
642     // Create a route for the connected network\r
643     //\r
644     Ip4Config->RouteTableSize    = 1;\r
645 \r
646     NetCopyMem (&Ip1, &Dhcp4Mode.ClientAddress, sizeof (IP4_ADDR));\r
647     NetCopyMem (&Ip2, &Dhcp4Mode.SubnetMask, sizeof (IP4_ADDR));\r
648     \r
649     Subnet = Ip1 & Ip2;\r
650 \r
651     NetCopyMem (&Ip4Config->RouteTable[0].SubnetAddress, &Subnet, sizeof (EFI_IPv4_ADDRESS));\r
652     NetCopyMem (&Ip4Config->RouteTable[0].SubnetMask, &Dhcp4Mode.SubnetMask, sizeof (EFI_IPv4_ADDRESS));\r
653     NetZeroMem (&Ip4Config->RouteTable[0].GatewayAddress, sizeof (EFI_IPv4_ADDRESS));\r
654 \r
655     //\r
656     // Create a route if there is a default router.\r
657     //\r
658     if (!EFI_IP4_EQUAL (&Dhcp4Mode.RouterAddress, &mZeroIp4Addr)) {\r
659       Ip4Config->RouteTableSize = 2;\r
660 \r
661       NetZeroMem (&Ip4Config->RouteTable[1].SubnetAddress, sizeof (EFI_IPv4_ADDRESS));\r
662       NetZeroMem (&Ip4Config->RouteTable[1].SubnetMask, sizeof (EFI_IPv4_ADDRESS));\r
663       NetCopyMem (&Ip4Config->RouteTable[1].GatewayAddress, &Dhcp4Mode.RouterAddress, sizeof (EFI_IPv4_ADDRESS));\r
664     }\r
665 \r
666     Instance->Result = EFI_SUCCESS;\r
667 \r
668     //\r
669     // ignore the return status of EfiNicIp4ConfigSetInfo. Network\r
670     // stack can operate even that failed.\r
671     //\r
672     EfiNicIp4ConfigSetInfo (&Instance->NicIp4Protocol, Instance->NicConfig, FALSE);\r
673   }\r
674 \r
675 ON_EXIT:\r
676   gBS->SignalEvent (Instance->DoneEvent);\r
677   Ip4ConfigCleanDhcp4 (Instance);\r
678   return ;\r
679 }\r
680 \r
681 \r
682 /**\r
683   Release all the DHCP related resources.\r
684 \r
685   @param  This                   The IP4 configure instance\r
686 \r
687   @return None\r
688 \r
689 **/\r
690 VOID\r
691 Ip4ConfigCleanDhcp4 (\r
692   IN IP4_CONFIG_INSTANCE    *This\r
693   )\r
694 {\r
695   if (This->Dhcp4 != NULL) {\r
696     This->Dhcp4->Stop (This->Dhcp4);\r
697 \r
698     gBS->CloseProtocol (\r
699           This->Dhcp4Handle,\r
700           &gEfiDhcp4ProtocolGuid,\r
701           This->Image,\r
702           This->Controller\r
703           );\r
704 \r
705     This->Dhcp4 = NULL;\r
706   }\r
707 \r
708   if (This->Dhcp4Handle != NULL) {\r
709     NetLibDestroyServiceChild (\r
710       This->Controller,\r
711       This->Image,\r
712       &gEfiDhcp4ServiceBindingProtocolGuid,\r
713       This->Dhcp4Handle\r
714       );\r
715 \r
716     This->Dhcp4Handle = NULL;\r
717   }\r
718 \r
719   if (This->Dhcp4Event == NULL) {\r
720     gBS->CloseEvent (This->Dhcp4Event);\r
721     This->Dhcp4Event = NULL;\r
722   }\r
723 }\r
724 \r
725 \r
726 /**\r
727   Clean up all the configuration parameters\r
728 \r
729   @param  Instance               The IP4 configure instance\r
730 \r
731   @return None\r
732 \r
733 **/\r
734 VOID\r
735 Ip4ConfigCleanConfig (\r
736   IN IP4_CONFIG_INSTANCE        *Instance\r
737   )\r
738 {\r
739   if (Instance->NicConfig != NULL) {\r
740     NetFreePool (Instance->NicConfig);\r
741     Instance->NicConfig = NULL;\r
742   }\r
743 \r
744   Instance->State         = IP4_CONFIG_STATE_IDLE;\r
745   Instance->DoneEvent     = NULL;\r
746   Instance->ReconfigEvent = NULL;\r
747 \r
748   Ip4ConfigCleanDhcp4 (Instance);\r
749 }\r
750 \r
751 EFI_IP4_CONFIG_PROTOCOL     mIp4ConfigProtocolTemplate = {\r
752   EfiIp4ConfigStart,\r
753   EfiIp4ConfigStop,\r
754   EfiIp4ConfigGetData\r
755 };\r
756 \r
757 EFI_NIC_IP4_CONFIG_PROTOCOL mNicIp4ConfigProtocolTemplate = {\r
758   EfiNicIp4ConfigGetName,\r
759   EfiNicIp4ConfigGetInfo,\r
760   EfiNicIp4ConfigSetInfo\r
761 };\r