pointer verification (not NULL) and buffer overrun fixes.
[mirror_edk2.git] / ShellPkg / Library / UefiShellNetwork1CommandsLib / Ifconfig.c
1 /** @file\r
2   The implementation for ifcommand shell command.\r
3 \r
4   Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>\r
5 \r
6   This program and the accompanying materials\r
7   are licensed and made available under the terms and conditions of the BSD License\r
8   which accompanies this distribution.  The full text of the license may be found at\r
9   http://opensource.org/licenses/bsd-license.php.\r
10 \r
11   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13 **/\r
14 \r
15 #include "UefiShellNetwork1CommandsLib.h"\r
16 \r
17 #define NIC_ITEM_CONFIG_SIZE   (sizeof (NIC_IP4_CONFIG_INFO) + sizeof (EFI_IP4_ROUTE_TABLE) * MAX_IP4_CONFIG_IN_VARIABLE)\r
18 #define EFI_IP4_TO_U32(EfiIpAddr)   (*(IP4_ADDR*)((EfiIpAddr).Addr))\r
19 \r
20 BOOLEAN                                 mIp4ConfigExist    = FALSE;\r
21 STATIC EFI_HII_CONFIG_ROUTING_PROTOCOL  *mHiiConfigRouting = NULL;\r
22 \r
23 STATIC CONST UINTN SEC_TO_NS            = 10000000;\r
24 STATIC CONST CHAR16 DhcpString[5]       = L"DHCP";\r
25 STATIC CONST CHAR16 StaticString[7]     = L"STATIC";\r
26 STATIC CONST CHAR16 PermanentString[10] = L"PERMANENT";\r
27 \r
28 typedef struct {\r
29   LIST_ENTRY                  Link;\r
30   EFI_HANDLE                  Handle;\r
31   NIC_ADDR                    NicAddress;\r
32   CHAR16                      Name[IP4_NIC_NAME_LENGTH];\r
33   BOOLEAN                     MediaPresentSupported;\r
34   BOOLEAN                     MediaPresent;\r
35   EFI_IP4_CONFIG_PROTOCOL     *Ip4Config;\r
36   NIC_IP4_CONFIG_INFO         *ConfigInfo;\r
37 } NIC_INFO;\r
38 \r
39 typedef struct {\r
40   EFI_IP_ADDRESS              DestIp;\r
41   EFI_MAC_ADDRESS             DestMac;\r
42   EFI_IP_ADDRESS              LocalIp;\r
43   EFI_MAC_ADDRESS             LocalMac;\r
44   UINT8                       MacLen;\r
45   EFI_EVENT                   OnResolved;\r
46   BOOLEAN                     Duplicate;\r
47 } ARP_REQUEST;\r
48 \r
49 STATIC CONST SHELL_PARAM_ITEM ParamList[] = {\r
50   {L"-c",     TypeValue},\r
51   {L"-l",     TypeValue},\r
52   {L"-s",     TypeMaxValue},\r
53   {NULL,      TypeMax}\r
54   };\r
55 \r
56 STATIC LIST_ENTRY                  NicInfoList;\r
57 STATIC BOOLEAN                     ArpResolved;\r
58 STATIC BOOLEAN                     mTimeout;\r
59 \r
60 /**\r
61   Count the space delimited items in a string.\r
62 \r
63   @param[in] String     A pointer to the string to count.\r
64 \r
65   @return The number of space-delimited items.\r
66   @retval 0xFF an error occured.\r
67 **/\r
68 UINT8\r
69 EFIAPI\r
70 CountSubItems (\r
71   IN CONST CHAR16 *String\r
72   )\r
73 {\r
74   CONST CHAR16  *Walker;\r
75   UINT8         Count;\r
76 \r
77   if (String == NULL || *String == CHAR_NULL) {\r
78     return (0xFF);\r
79   }\r
80 \r
81   for (Walker = String, Count = 0 ; Walker != NULL && *Walker != CHAR_NULL ; Walker = (StrStr(Walker, L" ")==NULL?NULL:StrStr(Walker, L" ")+1), Count++);\r
82   return (Count);\r
83 }\r
84 \r
85 /**\r
86   Find the NIC_INFO by the specified nic name.\r
87 \r
88   @param[in] Name     The pointer to the string containing the NIC name.\r
89   \r
90   @return The pointer to the NIC_INFO if there is a NIC_INFO named by Name.\r
91   @retval NULL  No NIC_INFO was found for Name.\r
92 **/\r
93 NIC_INFO*\r
94 EFIAPI\r
95 IfconfigFindNicByName (\r
96   IN CONST CHAR16           *Name\r
97   )\r
98 {\r
99   LIST_ENTRY                *Entry;\r
100   LIST_ENTRY                *NextEntry;\r
101   NIC_INFO                  *Info;\r
102   CHAR16                    *TempString;\r
103 \r
104   NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &NicInfoList) {\r
105     Info = BASE_CR (Entry, NIC_INFO, Link);\r
106     TempString = (CHAR16*)Info->Name;\r
107 \r
108     if (StringNoCaseCompare (&Name, &TempString) == 0) {\r
109       return Info;\r
110     }\r
111   }\r
112 \r
113   return NULL;\r
114 }\r
115 \r
116 /**\r
117   Tests whether a child handle is a child device of the controller.\r
118 \r
119   @param[in] ControllerHandle   A handle for a (parent) controller to test.\r
120   @param[in] ChildHandle        A child handle to test.\r
121   @param[in] ProtocolGuid       Supplies the protocol that the child controller\r
122                                 opens on its parent controller.\r
123 \r
124   @retval EFI_SUCCESS         ChildHandle is a child of the ControllerHandle.\r
125   @retval EFI_UNSUPPORTED     ChildHandle is not a child of the ControllerHandle.\r
126 **/\r
127 EFI_STATUS\r
128 EFIAPI\r
129 TestChildHandle (\r
130   IN CONST EFI_HANDLE       ControllerHandle,\r
131   IN CONST EFI_HANDLE       ChildHandle,\r
132   IN CONST EFI_GUID         *ProtocolGuid\r
133   )\r
134 {\r
135   EFI_STATUS                            Status;\r
136   EFI_OPEN_PROTOCOL_INFORMATION_ENTRY   *OpenInfoBuffer;\r
137   UINTN                                 EntryCount;\r
138   UINTN                                 Index;\r
139 \r
140   ASSERT (ProtocolGuid != NULL);\r
141 \r
142   //\r
143   // Retrieve the list of agents that are consuming the specific protocol\r
144   // on ControllerHandle.\r
145   //\r
146   Status = gBS->OpenProtocolInformation (\r
147                  ControllerHandle,\r
148                  (EFI_GUID *) ProtocolGuid,\r
149                  &OpenInfoBuffer,\r
150                  &EntryCount\r
151                  );\r
152   if (EFI_ERROR (Status)) {\r
153     return EFI_UNSUPPORTED;\r
154   }\r
155 \r
156   //\r
157   // Inspect if ChildHandle is one of the agents.\r
158   //\r
159   Status = EFI_UNSUPPORTED;\r
160   for (Index = 0; Index < EntryCount; Index++) {\r
161     if ((OpenInfoBuffer[Index].ControllerHandle == ChildHandle) &&\r
162         (OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {\r
163       Status = EFI_SUCCESS;\r
164       break;\r
165     }\r
166   }\r
167 \r
168   FreePool (OpenInfoBuffer);\r
169   return Status;\r
170 }\r
171 \r
172 /**\r
173   Get the child handle of the NIC handle.\r
174 \r
175   @param[in] Controller     Routing information: GUID.\r
176   @param[in] ChildHandle    Returned child handle.\r
177 \r
178   @retval EFI_SUCCESS         Successfully to get child handle.\r
179 **/\r
180 EFI_STATUS \r
181 GetChildHandle (\r
182   IN EFI_HANDLE         Controller,\r
183   OUT EFI_HANDLE        *ChildHandle\r
184   )\r
185 {\r
186   EFI_STATUS                 Status;\r
187   EFI_HANDLE                 *Handles;\r
188   UINTN                      HandleCount;\r
189   UINTN                      Index;\r
190   EFI_DEVICE_PATH_PROTOCOL   *ChildDeviceDevicePath;\r
191   VENDOR_DEVICE_PATH         *VendorDeviceNode;\r
192 \r
193   //\r
194   // Locate all EFI Hii Config Access protocols\r
195   //\r
196   Status = gBS->LocateHandleBuffer (\r
197                  ByProtocol,\r
198                  &gEfiHiiConfigAccessProtocolGuid,\r
199                  NULL,\r
200                  &HandleCount,\r
201                  &Handles\r
202                  );\r
203   if (EFI_ERROR (Status) || (HandleCount == 0)) {\r
204     return Status;\r
205   }\r
206 \r
207   Status = EFI_NOT_FOUND;\r
208 \r
209   for (Index = 0; Index < HandleCount; Index++) {\r
210   \r
211     Status = TestChildHandle (Controller, Handles[Index], &gEfiManagedNetworkServiceBindingProtocolGuid);\r
212     if (!EFI_ERROR (Status)) {\r
213       //\r
214       // Get device path on the child handle\r
215       //\r
216       Status = gBS->HandleProtocol (\r
217                      Handles[Index],\r
218                      &gEfiDevicePathProtocolGuid,\r
219                      (VOID **) &ChildDeviceDevicePath\r
220                      );\r
221       \r
222       if (!EFI_ERROR (Status)) {\r
223         while (!IsDevicePathEnd (ChildDeviceDevicePath)) {\r
224           ChildDeviceDevicePath = NextDevicePathNode (ChildDeviceDevicePath);\r
225           //\r
226           // Parse one instance\r
227           //\r
228           if (ChildDeviceDevicePath->Type == HARDWARE_DEVICE_PATH && \r
229               ChildDeviceDevicePath->SubType == HW_VENDOR_DP) {\r
230             VendorDeviceNode = (VENDOR_DEVICE_PATH *) ChildDeviceDevicePath;\r
231             if (CompareMem (&VendorDeviceNode->Guid, &gEfiNicIp4ConfigVariableGuid, sizeof (EFI_GUID)) == 0) {\r
232               //\r
233               // Found item matched gEfiNicIp4ConfigVariableGuid\r
234               //\r
235               *ChildHandle = Handles[Index];\r
236               FreePool (Handles);\r
237               return EFI_SUCCESS;\r
238             }\r
239           }\r
240         }\r
241       }      \r
242     }\r
243   }\r
244 \r
245   FreePool (Handles);\r
246   return Status;  \r
247 }\r
248 \r
249 /**\r
250   Append OFFSET/WIDTH/VALUE items at the beginning of string.\r
251 \r
252   @param[in,out]  String      The pointer to the string to append onto.\r
253   @param[in]      Offset      Offset value.\r
254   @param[in]      Width       Width value.\r
255   @param[in]      Block       Point to data buffer.\r
256 \r
257   @return The count of unicode character that were appended.\r
258 **/\r
259 UINTN\r
260 EFIAPI\r
261 AppendOffsetWidthValue (\r
262   IN OUT CHAR16               *String,\r
263   IN UINTN                    Offset,\r
264   IN UINTN                    Width,\r
265   IN CONST UINT8              *Block\r
266   )\r
267 \r
268 {\r
269   CHAR16                      *OriString;\r
270 \r
271   OriString = String;\r
272 \r
273   StrCpy (String, L"&OFFSET=");\r
274   String += StrLen (L"&OFFSET=");\r
275   String += UnicodeSPrint (String, 20, L"%x", Offset);\r
276 \r
277   StrCpy (String,L"&WIDTH=");\r
278   String += StrLen (L"&WIDTH=");\r
279   String += UnicodeSPrint (String, 20, L"%x", Width);\r
280 \r
281   if (Block != NULL) {\r
282     StrCpy (String,L"&VALUE=");\r
283     String += StrLen (L"&VALUE=");\r
284     while ((Width--) != 0) {\r
285       String += UnicodeSPrint (String, 20, L"%x", Block[Width]);\r
286     }\r
287   }\r
288   \r
289   return String - OriString;\r
290 }\r
291 \r
292 /**\r
293   Converts the unicode character of the string from uppercase to lowercase.\r
294   This is a internal function.\r
295 \r
296   @param ConfigString  String to be converted\r
297 **/\r
298 CHAR16* \r
299 EFIAPI\r
300 HiiToLower (\r
301   IN CHAR16   *ConfigString\r
302   )\r
303 {\r
304   CHAR16      *String;\r
305   BOOLEAN     Lower;\r
306 \r
307   //\r
308   // Convert all hex digits in range [A-F] in the configuration header to [a-f]\r
309   //\r
310   for (String = ConfigString, Lower = FALSE; String != NULL && *String != L'\0'; String++) {\r
311     if (*String == L'=') {\r
312       Lower = TRUE;\r
313     } else if (*String == L'&') {\r
314       Lower = FALSE;\r
315     } else if (Lower && *String >= L'A' && *String <= L'F') {\r
316       *String = (CHAR16) (*String - L'A' + L'a');\r
317     }\r
318   }\r
319 \r
320   return (ConfigString);\r
321 }\r
322 \r
323 \r
324 /**\r
325   Construct <ConfigHdr> using routing information GUID/NAME/PATH.\r
326 \r
327   @param[in] Guid         Routing information: GUID.\r
328   @param[in] Name         Routing information: NAME.\r
329   @param[in] DriverHandle Driver handle which contains the routing information: PATH.\r
330 \r
331   @retval NULL            An error occured.\r
332   @return                 The pointer to configHdr string.\r
333 **/\r
334 CHAR16 *\r
335 EFIAPI\r
336 ConstructConfigHdr (\r
337   IN CONST EFI_GUID          *Guid,\r
338   IN CONST CHAR16            *Name,\r
339   IN EFI_HANDLE              DriverHandle\r
340   )\r
341 {\r
342   EFI_STATUS                 Status;\r
343   CHAR16                     *ConfigHdr;\r
344   EFI_DEVICE_PATH_PROTOCOL   *DevicePath;\r
345   CHAR16                     *String;\r
346   UINTN                      Index;\r
347   UINT8                      *Buffer;\r
348   UINTN                      DevicePathLength;\r
349   UINTN                      NameLength;\r
350 \r
351   //\r
352   // Get the device path from handle installed EFI HII Config Access protocol\r
353   //\r
354   Status = gBS->HandleProtocol (\r
355                  DriverHandle,\r
356                  &gEfiDevicePathProtocolGuid,\r
357                  (VOID **) &DevicePath\r
358                  );\r
359   if (EFI_ERROR (Status)) {\r
360     return NULL;\r
361   }\r
362 \r
363   DevicePathLength = GetDevicePathSize (DevicePath);\r
364   NameLength = StrLen (Name);\r
365   ConfigHdr = AllocateZeroPool ((5 + sizeof (EFI_GUID) * 2 + 6 + NameLength * 4 + 6 + DevicePathLength * 2 + 1) * sizeof (CHAR16));\r
366   if (ConfigHdr == NULL) {\r
367     return NULL;\r
368   } \r
369 \r
370   String = ConfigHdr;\r
371   StrCpy (String, L"GUID=");\r
372   String += StrLen (L"GUID=");\r
373 \r
374   //\r
375   // Append Guid converted to <HexCh>32\r
376   //\r
377   for (Index = 0, Buffer = (UINT8 *)Guid; Index < sizeof (EFI_GUID); Index++) {\r
378     String += UnicodeSPrint (String, 6, L"%02x", *Buffer++);\r
379   }\r
380 \r
381   //\r
382   // Append L"&NAME="\r
383   //\r
384   StrCpy (String, L"&NAME=");\r
385   String += StrLen (L"&NAME=");\r
386   for (Index = 0; Index < NameLength ; Index++) {\r
387     String += UnicodeSPrint (String, 10, L"00%x", Name[Index]);\r
388   }\r
389   \r
390   //\r
391   // Append L"&PATH="\r
392   //\r
393   StrCpy (String, L"&PATH=");\r
394   String += StrLen (L"&PATH=");\r
395   for (Index = 0, Buffer = (UINT8 *) DevicePath; Index < DevicePathLength; Index++) {\r
396     String += UnicodeSPrint (String, 6, L"%02x", *Buffer++);\r
397   }\r
398 \r
399   return (HiiToLower(ConfigHdr));\r
400 }\r
401 \r
402 /**\r
403   Get network physical device NIC information.\r
404 \r
405   @param[in] Handle         The network physical device handle.\r
406   @param[out] NicAddr       NIC information.\r
407 \r
408   @retval EFI_SUCCESS         Get NIC information successfully.\r
409 **/                  \r
410 EFI_STATUS\r
411 EFIAPI\r
412 IfConfigGetNicMacInfo (\r
413   IN  EFI_HANDLE                    Handle,\r
414   OUT NIC_ADDR                      *NicAddr\r
415   )    \r
416 {\r
417   EFI_STATUS                    Status;\r
418   EFI_HANDLE                    MnpHandle;\r
419   EFI_SIMPLE_NETWORK_MODE       SnpMode;\r
420   EFI_MANAGED_NETWORK_PROTOCOL  *Mnp;\r
421 \r
422   MnpHandle = NULL;\r
423   Mnp       = NULL;\r
424 \r
425   Status = NetLibCreateServiceChild (\r
426              Handle,\r
427              gImageHandle, \r
428              &gEfiManagedNetworkServiceBindingProtocolGuid,\r
429              &MnpHandle\r
430              );\r
431   if (EFI_ERROR (Status)) {\r
432     return Status;\r
433   }\r
434 \r
435   Status = gBS->HandleProtocol (\r
436                   MnpHandle,\r
437                   &gEfiManagedNetworkProtocolGuid,\r
438                   (VOID **) &Mnp\r
439                   );\r
440   if (EFI_ERROR (Status)) {\r
441     goto ON_ERROR;\r
442   }\r
443 \r
444   Status = Mnp->GetModeData (Mnp, NULL, &SnpMode);\r
445   if (EFI_ERROR (Status) && (Status != EFI_NOT_STARTED)) {\r
446     goto ON_ERROR;\r
447   }\r
448  \r
449   NicAddr->Type    = (UINT16) SnpMode.IfType;\r
450   NicAddr->Len     = (UINT8) SnpMode.HwAddressSize;\r
451   CopyMem (&NicAddr->MacAddr, &SnpMode.CurrentAddress, NicAddr->Len);\r
452 \r
453 ON_ERROR:\r
454 \r
455   NetLibDestroyServiceChild (\r
456     Handle,\r
457     gImageHandle, \r
458     &gEfiManagedNetworkServiceBindingProtocolGuid,\r
459     MnpHandle\r
460     );\r
461 \r
462   return Status;\r
463 \r
464 }\r
465 \r
466 /**\r
467   Get network physical device NIC information.\r
468 \r
469   @param[in] Handle         The network physical device handle.\r
470   @param[out] MediaPresentSupported\r
471                             Upon successful return, TRUE is media present \r
472                             is supported.  FALSE otherwise.\r
473   @param[out] MediaPresent  Upon successful return, TRUE is media present \r
474                             is enabled.  FALSE otherwise.\r
475 \r
476   @retval EFI_SUCCESS       The operation was successful.\r
477 **/\r
478 EFI_STATUS\r
479 EFIAPI\r
480 IfConfigGetNicMediaStatus (\r
481   IN  EFI_HANDLE                    Handle,\r
482   OUT BOOLEAN                       *MediaPresentSupported,\r
483   OUT BOOLEAN                       *MediaPresent\r
484   )    \r
485                   \r
486 {\r
487   EFI_STATUS                    Status;\r
488   EFI_HANDLE                    MnpHandle;\r
489   EFI_SIMPLE_NETWORK_MODE       SnpMode;\r
490   EFI_MANAGED_NETWORK_PROTOCOL  *Mnp;\r
491 \r
492   MnpHandle = NULL;\r
493   Mnp       = NULL;\r
494 \r
495   Status = NetLibCreateServiceChild (\r
496              Handle,\r
497              gImageHandle, \r
498              &gEfiManagedNetworkServiceBindingProtocolGuid,\r
499              &MnpHandle\r
500              );\r
501   if (EFI_ERROR (Status)) {\r
502     return Status;\r
503   }\r
504 \r
505   Status = gBS->HandleProtocol (\r
506                   MnpHandle,\r
507                   &gEfiManagedNetworkProtocolGuid,\r
508                   (VOID **) &Mnp\r
509                   );\r
510   if (EFI_ERROR (Status)) {\r
511     goto ON_ERROR;\r
512   }\r
513 \r
514   Status = Mnp->GetModeData (Mnp, NULL, &SnpMode);\r
515   if (EFI_ERROR (Status) && (Status != EFI_NOT_STARTED)) {\r
516     goto ON_ERROR;\r
517   }\r
518  \r
519   *MediaPresentSupported = SnpMode.MediaPresentSupported;\r
520   *MediaPresent = SnpMode.MediaPresent;\r
521 \r
522 ON_ERROR:\r
523 \r
524   NetLibDestroyServiceChild (\r
525     Handle,\r
526     gImageHandle, \r
527     &gEfiManagedNetworkServiceBindingProtocolGuid,\r
528     MnpHandle\r
529     );\r
530 \r
531   return Status;\r
532 \r
533 }\r
534 \r
535 /**\r
536   Get all Nic's information through HII service.\r
537 \r
538   @retval EFI_SUCCESS         All the nic information is collected.\r
539 **/\r
540 EFI_STATUS\r
541 EFIAPI\r
542 IfconfigGetAllNicInfoByHii (\r
543   VOID\r
544   )\r
545 {\r
546   EFI_STATUS                    Status;\r
547   EFI_HANDLE                    *Handles;\r
548   UINTN                         HandleCount;\r
549   CHAR16                        *ConfigResp;\r
550   CHAR16                        *ConfigHdr;\r
551   UINTN                         Index;\r
552   CHAR16                        *AccessProgress;\r
553   CHAR16                        *AccessResults;\r
554   UINTN                         BufferSize;\r
555   NIC_INFO                      *NicInfo;\r
556   NIC_IP4_CONFIG_INFO           *NicConfigRequest;\r
557   NIC_IP4_CONFIG_INFO           *NicConfig;\r
558   CHAR16                        *String;\r
559   UINTN                         Length;\r
560   UINTN                         Offset;\r
561   EFI_HANDLE                    ChildHandle;\r
562 \r
563   AccessResults    = NULL;\r
564   ConfigHdr        = NULL;\r
565   ConfigResp       = NULL;\r
566   NicConfigRequest = NULL;\r
567   NicInfo          = NULL;\r
568 \r
569   InitializeListHead (&NicInfoList);\r
570 \r
571   //\r
572   // Check if HII Config Routing protocol available.\r
573   //\r
574   Status = gBS->LocateProtocol (\r
575                 &gEfiHiiConfigRoutingProtocolGuid,\r
576                 NULL,\r
577                 (VOID**)&mHiiConfigRouting\r
578                 );\r
579   if (EFI_ERROR (Status)) {\r
580     return EFI_NOT_FOUND;\r
581   }\r
582 \r
583   //\r
584   // Locate all network device handles\r
585   //\r
586   Status = gBS->LocateHandleBuffer (\r
587                  ByProtocol,\r
588                  &gEfiManagedNetworkServiceBindingProtocolGuid,\r
589                  NULL,\r
590                  &HandleCount,\r
591                  &Handles\r
592                  );\r
593   if (EFI_ERROR (Status) || (HandleCount == 0)) {\r
594     return EFI_NOT_FOUND;\r
595   }\r
596 \r
597   for (Index = 0; Index < HandleCount; Index++) {\r
598     Status = GetChildHandle (Handles[Index], &ChildHandle);\r
599     if (EFI_ERROR (Status)) {\r
600       //\r
601       // If failed to get Child handle, try NIC controller handle for back-compatibility.\r
602       //\r
603       ChildHandle = Handles[Index];\r
604     }\r
605     //\r
606     // Construct configuration request string header\r
607     //\r
608     ConfigHdr = ConstructConfigHdr (&gEfiNicIp4ConfigVariableGuid, EFI_NIC_IP4_CONFIG_VARIABLE, ChildHandle);\r
609     if (ConfigHdr != NULL) {\r
610       Length = StrLen (ConfigHdr);\r
611     } else {\r
612       Length = 0;\r
613     }\r
614     ConfigResp = AllocateZeroPool ((Length + NIC_ITEM_CONFIG_SIZE * 2 + 100) * sizeof (CHAR16));\r
615     if (ConfigResp == NULL) {\r
616       Status = EFI_OUT_OF_RESOURCES;\r
617       goto ON_ERROR;\r
618     }\r
619     if (ConfigHdr != NULL) {\r
620       StrCpy (ConfigResp, ConfigHdr);\r
621     }\r
622  \r
623     //\r
624     // Append OFFSET/WIDTH pair\r
625     //\r
626     String = ConfigResp + Length;\r
627     Offset = 0;\r
628     AppendOffsetWidthValue (String, Offset, NIC_ITEM_CONFIG_SIZE, NULL);\r
629 \r
630     NicInfo = AllocateZeroPool (sizeof (NIC_INFO));\r
631     if (NicInfo == NULL) {\r
632       Status = EFI_OUT_OF_RESOURCES;\r
633       goto ON_ERROR;\r
634     }\r
635     NicInfo->Handle       = Handles[Index];\r
636 \r
637     //\r
638     // Get network physical devcie MAC information\r
639     //\r
640     IfConfigGetNicMacInfo (Handles[Index], &NicInfo->NicAddress);\r
641     if (NicInfo->NicAddress.Type == NET_IFTYPE_ETHERNET) {\r
642       UnicodeSPrint (NicInfo->Name, IP4_NIC_NAME_LENGTH, L"eth%d", Index);\r
643     } else {\r
644       UnicodeSPrint (NicInfo->Name, IP4_NIC_NAME_LENGTH, L"unk%d", Index);\r
645     }\r
646 \r
647     //\r
648     // Get media status\r
649     //\r
650     IfConfigGetNicMediaStatus (Handles[Index], &NicInfo->MediaPresentSupported, &NicInfo->MediaPresent);\r
651 \r
652     NicConfigRequest = AllocateZeroPool (NIC_ITEM_CONFIG_SIZE);\r
653     if (NicConfigRequest == NULL) {\r
654       Status = EFI_OUT_OF_RESOURCES;\r
655       goto ON_ERROR;\r
656     }\r
657 \r
658     //\r
659     // Get network parameters by HII service\r
660     //\r
661     Status = mHiiConfigRouting->ExtractConfig (\r
662                                   mHiiConfigRouting,\r
663                                   ConfigResp,\r
664                                   &AccessProgress,\r
665                                   &AccessResults\r
666                                   );\r
667     if (!EFI_ERROR (Status)) {\r
668       BufferSize = NIC_ITEM_CONFIG_SIZE;\r
669       Status = mHiiConfigRouting->ConfigToBlock (\r
670                                     mHiiConfigRouting,\r
671                                     AccessResults,\r
672                                     (UINT8 *) NicConfigRequest,\r
673                                     &BufferSize,\r
674                                     &AccessProgress\r
675                                     );\r
676       if (!EFI_ERROR (Status)) {\r
677         BufferSize = sizeof (NIC_IP4_CONFIG_INFO) + sizeof (EFI_IP4_ROUTE_TABLE) * NicConfigRequest->Ip4Info.RouteTableSize;\r
678         NicConfig = AllocateZeroPool (BufferSize);\r
679         if (NicConfig == NULL) {\r
680           Status = EFI_OUT_OF_RESOURCES;\r
681           goto ON_ERROR;\r
682         }\r
683         CopyMem (NicConfig, NicConfigRequest, BufferSize);\r
684 \r
685         //\r
686         // If succeeds to get NIC configuration, fix up routetable pointer.\r
687         //\r
688         NicConfig->Ip4Info.RouteTable = (EFI_IP4_ROUTE_TABLE *) (&NicConfig->Ip4Info + 1);\r
689         NicInfo->ConfigInfo   = NicConfig;\r
690 \r
691       } else {\r
692         NicInfo->ConfigInfo   = NULL;\r
693       }\r
694 \r
695       FreePool (AccessResults);\r
696 \r
697     } else {\r
698       NicInfo->ConfigInfo   = NULL;\r
699     }\r
700 \r
701     //\r
702     // Add the Nic's info to the global NicInfoList.\r
703     //\r
704     InsertTailList (&NicInfoList, &NicInfo->Link);\r
705 \r
706     FreePool (NicConfigRequest);\r
707     FreePool (ConfigResp);\r
708     FreePool (ConfigHdr);\r
709   }\r
710 \r
711   FreePool (Handles);\r
712 \r
713   return EFI_SUCCESS;\r
714  \r
715 ON_ERROR:\r
716   if (AccessResults != NULL) {\r
717     FreePool (AccessResults);\r
718   }\r
719   if (NicConfigRequest != NULL) {\r
720     FreePool (NicConfigRequest);\r
721   }\r
722   if (NicInfo != NULL) {\r
723     FreePool (NicInfo);\r
724   }\r
725   if (ConfigResp != NULL) {\r
726     FreePool (ConfigResp);\r
727   }\r
728   if (ConfigHdr != NULL) {\r
729     FreePool (ConfigHdr);\r
730   }\r
731 \r
732   FreePool (Handles);\r
733 \r
734   return Status;\r
735 }\r
736 \r
737 /**\r
738   Set the address for the specified nic by HII service.\r
739 \r
740   @param[in] NicInfo    A pointer to the NIC_INFO of the Nic to be configured.\r
741   @param[in] Config     The command line arguments for the set operation.\r
742 \r
743   @retval EFI_SUCCESS         The address set operation is done.\r
744 **/\r
745 SHELL_STATUS\r
746 EFIAPI\r
747 IfconfigSetNicAddrByHii (\r
748   IN CONST NIC_INFO                 *NicInfo,\r
749   IN CONST NIC_IP4_CONFIG_INFO      *Config\r
750   )\r
751 {\r
752   EFI_STATUS                    Status;\r
753   SHELL_STATUS                  ShellStatus;\r
754   NIC_IP4_CONFIG_INFO           *NicConfig;\r
755   CHAR16                        *ConfigResp;\r
756   CHAR16                        *ConfigHdr;\r
757   CHAR16                        *AccessProgress;\r
758   CHAR16                        *AccessResults;\r
759   CHAR16                        *String;\r
760   UINTN                         Length;\r
761   UINTN                         Offset;\r
762   EFI_HANDLE                    ChildHandle;\r
763 \r
764   AccessResults  = NULL;\r
765   ConfigHdr      = NULL;\r
766   ConfigResp     = NULL;\r
767   NicConfig      = NULL;\r
768   ShellStatus    = SHELL_SUCCESS;\r
769 \r
770   Status = GetChildHandle (NicInfo->Handle, &ChildHandle);\r
771   if (EFI_ERROR (Status)) {\r
772     //\r
773     // If failed to get Child handle, try NIC controller handle for back-compatibility\r
774     //\r
775     ChildHandle = NicInfo->Handle;\r
776   }\r
777   //\r
778   // Construct config request string header\r
779   //\r
780   ConfigHdr = ConstructConfigHdr (&gEfiNicIp4ConfigVariableGuid, EFI_NIC_IP4_CONFIG_VARIABLE, ChildHandle);\r
781   if (ConfigHdr != NULL) {\r
782     Length = StrLen (ConfigHdr);\r
783   } else {\r
784     Length = 0;\r
785   }\r
786   ConfigResp = AllocateZeroPool ((Length + NIC_ITEM_CONFIG_SIZE * 2 + 100) * sizeof (CHAR16));\r
787   if (ConfigHdr != NULL) {\r
788     StrCpy (ConfigResp, ConfigHdr);\r
789   }\r
790 \r
791   NicConfig = AllocateZeroPool (NIC_ITEM_CONFIG_SIZE);\r
792   if (NicConfig == NULL) {\r
793     ShellStatus = SHELL_OUT_OF_RESOURCES;\r
794     goto ON_EXIT;\r
795   }\r
796 \r
797   if (Config != NULL) {\r
798     CopyMem (NicConfig, Config, sizeof (NIC_IP4_CONFIG_INFO) + sizeof (EFI_IP4_ROUTE_TABLE) * Config->Ip4Info.RouteTableSize);\r
799   }\r
800 \r
801   //\r
802   // Append OFFSET/WIDTH pair\r
803   //\r
804   String = ConfigResp + Length;\r
805   Offset = 0;\r
806   AppendOffsetWidthValue (String, Offset, NIC_ITEM_CONFIG_SIZE, NULL);\r
807 \r
808   //\r
809   // Call HII helper function to generate configuration string\r
810   //\r
811   Status = mHiiConfigRouting->BlockToConfig (\r
812                                 mHiiConfigRouting,\r
813                                 ConfigResp,\r
814                                 (UINT8 *) NicConfig,\r
815                                 NIC_ITEM_CONFIG_SIZE,\r
816                                 &AccessResults,\r
817                                 &AccessProgress\r
818                                 );\r
819   if (EFI_ERROR (Status)) {\r
820     ShellStatus = SHELL_NOT_FOUND;\r
821     goto ON_EXIT;\r
822   }\r
823 \r
824   //\r
825   // Set IP setting by HII servie\r
826   //\r
827   Status = mHiiConfigRouting->RouteConfig (\r
828                                 mHiiConfigRouting,\r
829                                 AccessResults,\r
830                                 &AccessProgress\r
831                                 );\r
832   if (EFI_ERROR(Status)) {\r
833     ShellStatus = SHELL_ACCESS_DENIED;\r
834   }\r
835 \r
836 ON_EXIT:\r
837   SHELL_FREE_NON_NULL(AccessResults);\r
838   SHELL_FREE_NON_NULL(NicConfig);\r
839   SHELL_FREE_NON_NULL(ConfigResp);\r
840   SHELL_FREE_NON_NULL(ConfigHdr);\r
841 \r
842   return ShellStatus;\r
843 }\r
844 \r
845 /**\r
846   The callback function for the Arp address resolved event.\r
847 \r
848   @param[in] Event    The event this function is registered to.\r
849   @param[in] Context  The context registered to the event.\r
850 **/\r
851 VOID\r
852 EFIAPI\r
853 IfconfigOnArpResolved (\r
854   IN EFI_EVENT                  Event,\r
855   IN VOID                       *Context\r
856   )\r
857 {\r
858   ARP_REQUEST                   *Request;\r
859   UINT8                         Index;\r
860 \r
861   Request = (ARP_REQUEST *) Context;\r
862   ASSERT (Request != NULL);\r
863 \r
864   Request->Duplicate = FALSE;\r
865   \r
866   if (0 == CompareMem (&Request->LocalMac, &Request->DestMac, Request->MacLen)) {\r
867     ShellPrintHiiEx(\r
868       -1, \r
869       -1, \r
870       NULL,\r
871       STRING_TOKEN (STR_IFCONFIG_SHOW_IP_ADDR), \r
872       gShellNetwork1HiiHandle, \r
873       L"Already Configured",\r
874       (UINTN)Request->DestIp.v4.Addr[0],\r
875       (UINTN)Request->DestIp.v4.Addr[1],\r
876       (UINTN)Request->DestIp.v4.Addr[2],\r
877       (UINTN)Request->DestIp.v4.Addr[3]\r
878       );\r
879     ArpResolved = TRUE;\r
880     return;\r
881   }\r
882   \r
883   for (Index = 0; Index < Request->MacLen; Index++) {\r
884     if (Request->DestMac.Addr[Index] != 0) {\r
885       Request->Duplicate = TRUE;\r
886     }\r
887   }\r
888 \r
889   if (Request->Duplicate) {\r
890     ShellPrintHiiEx(\r
891     -1,\r
892     -1,\r
893     NULL,\r
894     STRING_TOKEN(STR_IFCONFIG_CONF_IP_ADDR), \r
895     gShellNetwork1HiiHandle, \r
896     (UINTN)Request->DestMac.Addr[0], \r
897     (UINTN)Request->DestMac.Addr[1], \r
898     (UINTN)Request->DestMac.Addr[2],\r
899     (UINTN)Request->DestMac.Addr[3], \r
900     (UINTN)Request->DestMac.Addr[4], \r
901     (UINTN)Request->DestMac.Addr[5]\r
902     );    \r
903   }\r
904 \r
905   ArpResolved = TRUE;\r
906   return ;\r
907 }\r
908 \r
909 /**\r
910   Check whether the address to be configured conflicts with other hosts.\r
911 \r
912   @param[in] NicInfo    The pointer to the NIC_INFO of the Nic to be configured.\r
913   @param[in] IpAddr     The IPv4 address to be configured to the Nic.\r
914 \r
915   @return TRUE      Some other host already uses the IpAddr.\r
916   @return FALSE     The address is unused.\r
917 **/\r
918 BOOLEAN\r
919 EFIAPI\r
920 IfconfigIsIpDuplicate (\r
921   IN  NIC_INFO                  *NicInfo,\r
922   IN  IP4_ADDR                  IpAddr\r
923   )\r
924 {\r
925   EFI_ARP_PROTOCOL              *Arp;\r
926   EFI_ARP_CONFIG_DATA           ArpCfgData;\r
927   EFI_HANDLE                    ArpHandle;\r
928   ARP_REQUEST                   Request;\r
929   EFI_STATUS                    Status;\r
930 \r
931   Arp           = NULL;\r
932   ArpHandle     = NULL;\r
933   ZeroMem (&Request, sizeof (ARP_REQUEST));\r
934 \r
935   Status = NetLibCreateServiceChild (\r
936              NicInfo->Handle,\r
937              gImageHandle, \r
938              &gEfiArpServiceBindingProtocolGuid,\r
939              &ArpHandle\r
940              );\r
941 \r
942   if (EFI_ERROR (Status)) {\r
943     return FALSE;\r
944   }\r
945 \r
946   Status = gBS->OpenProtocol (\r
947                  ArpHandle,\r
948                  &gEfiArpProtocolGuid,\r
949                  (VOID**)&Arp,\r
950                  gImageHandle,\r
951                  ArpHandle,\r
952                  EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
953                  );\r
954 \r
955   if (EFI_ERROR (Status)) {\r
956     goto ON_EXIT;\r
957   }\r
958 \r
959   //\r
960   // Set up the Arp requests\r
961   //\r
962   EFI_IP4_TO_U32 (Request.DestIp.v4)  = IpAddr;\r
963   EFI_IP4_TO_U32 (Request.LocalIp.v4) = 0xffffffff;\r
964   Request.LocalMac                    = NicInfo->NicAddress.MacAddr;\r
965   Request.MacLen                      = NicInfo->NicAddress.Len;\r
966   \r
967   Status = gBS->CreateEvent (\r
968                  EVT_NOTIFY_SIGNAL,\r
969                  TPL_CALLBACK,\r
970                  IfconfigOnArpResolved,\r
971                  (VOID *) &Request,\r
972                  &Request.OnResolved\r
973                  );\r
974   \r
975   if (EFI_ERROR (Status)) {\r
976     goto ON_EXIT;\r
977   }\r
978   \r
979   ArpCfgData.SwAddressType    = 0x0800;\r
980   ArpCfgData.SwAddressLength  = 4;\r
981   ArpCfgData.StationAddress   = &Request.LocalIp;\r
982   ArpCfgData.EntryTimeOut     = 0;\r
983   ArpCfgData.RetryCount       = 3;\r
984   ArpCfgData.RetryTimeOut     = 0;\r
985   \r
986   Status = Arp->Configure (Arp, &ArpCfgData);\r
987   \r
988   if (EFI_ERROR (Status)) {\r
989     goto ON_EXIT;\r
990   }\r
991 \r
992   Status = Arp->Request (\r
993                   Arp,\r
994                   &Request.DestIp,\r
995                   Request.OnResolved,\r
996                   &Request.DestMac\r
997                   );\r
998   \r
999   if (EFI_ERROR (Status) && (Status != EFI_NOT_READY)) {\r
1000     goto ON_EXIT;\r
1001   }\r
1002 \r
1003   while (!ArpResolved) {\r
1004     \r
1005   }\r
1006 \r
1007 ON_EXIT:\r
1008   if (Request.OnResolved != NULL) {\r
1009     gBS->CloseEvent (Request.OnResolved);\r
1010   }\r
1011 \r
1012   NetLibDestroyServiceChild (\r
1013     NicInfo->Handle, \r
1014     gImageHandle, \r
1015     &gEfiArpServiceBindingProtocolGuid, \r
1016     ArpHandle\r
1017     );\r
1018 \r
1019   return Request.Duplicate;\r
1020 }\r
1021 \r
1022 /**\r
1023   The callback function for the timer event used to get map.\r
1024 \r
1025   @param[in] Event    The event this function is registered to.\r
1026   @param[in] Context  The context registered to the event.\r
1027 **/\r
1028 VOID\r
1029 EFIAPI\r
1030 TimeoutToGetMap (\r
1031   IN EFI_EVENT      Event,\r
1032   IN VOID           *Context\r
1033   )\r
1034 {\r
1035   mTimeout = TRUE;\r
1036   return ;\r
1037 }\r
1038 \r
1039 /**\r
1040   Create an IP child, use it to start the auto configuration, then destory it.\r
1041 \r
1042   @param[in] NicInfo    The pointer to the NIC_INFO of the Nic to be configured.\r
1043 \r
1044   @retval EFI_SUCCESS         The configuration is done.\r
1045 **/\r
1046 EFI_STATUS\r
1047 EFIAPI\r
1048 IfconfigStartIp4(\r
1049   IN NIC_INFO                   *NicInfo\r
1050   )\r
1051 {\r
1052   EFI_IP4_PROTOCOL              *Ip4;\r
1053   EFI_HANDLE                    Ip4Handle;\r
1054   EFI_HANDLE                    TimerToGetMap;\r
1055   EFI_IP4_CONFIG_DATA           Ip4ConfigData;\r
1056   EFI_IP4_MODE_DATA             Ip4Mode;\r
1057   EFI_STATUS                    Status;\r
1058 \r
1059   //\r
1060   // Get the Ip4ServiceBinding Protocol\r
1061   //\r
1062   Ip4Handle     = NULL;\r
1063   Ip4           = NULL;\r
1064   TimerToGetMap = NULL;\r
1065 \r
1066   ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_START_SET_ADDR), gShellNetwork1HiiHandle);\r
1067 \r
1068   Status = NetLibCreateServiceChild (\r
1069              NicInfo->Handle,\r
1070              gImageHandle,\r
1071              &gEfiIp4ServiceBindingProtocolGuid,\r
1072              &Ip4Handle\r
1073              );\r
1074 \r
1075   if (EFI_ERROR (Status)) {\r
1076     return Status;\r
1077   }\r
1078 \r
1079   Status = gBS->OpenProtocol (\r
1080                  Ip4Handle,\r
1081                  &gEfiIp4ProtocolGuid,\r
1082                  (VOID **) &Ip4,\r
1083                  NicInfo->Handle,\r
1084                  gImageHandle,\r
1085                  EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
1086                  );\r
1087 \r
1088   if (EFI_ERROR (Status)) {\r
1089     goto ON_EXIT;\r
1090   }\r
1091 \r
1092   Ip4ConfigData.DefaultProtocol          = EFI_IP_PROTO_ICMP;\r
1093   Ip4ConfigData.AcceptAnyProtocol        = FALSE;\r
1094   Ip4ConfigData.AcceptIcmpErrors         = FALSE;\r
1095   Ip4ConfigData.AcceptBroadcast          = FALSE;\r
1096   Ip4ConfigData.AcceptPromiscuous        = FALSE;\r
1097   Ip4ConfigData.UseDefaultAddress        = TRUE;\r
1098   ZeroMem (&Ip4ConfigData.StationAddress, sizeof (EFI_IPv4_ADDRESS));\r
1099   ZeroMem (&Ip4ConfigData.SubnetMask, sizeof (EFI_IPv4_ADDRESS));\r
1100   Ip4ConfigData.TypeOfService            = 0;\r
1101   Ip4ConfigData.TimeToLive               = 1;\r
1102   Ip4ConfigData.DoNotFragment            = FALSE;\r
1103   Ip4ConfigData.RawData                  = FALSE;\r
1104   Ip4ConfigData.ReceiveTimeout           = 0;\r
1105   Ip4ConfigData.TransmitTimeout          = 0;\r
1106 \r
1107   Status = Ip4->Configure (Ip4, &Ip4ConfigData);\r
1108 \r
1109   if (Status == EFI_NO_MAPPING) {\r
1110     mTimeout = FALSE;\r
1111     Status  = gBS->CreateEvent (\r
1112                     EVT_NOTIFY_SIGNAL | EVT_TIMER,\r
1113                     TPL_CALLBACK - 1,\r
1114                     TimeoutToGetMap,\r
1115                     NULL,\r
1116                     &TimerToGetMap\r
1117                     );\r
1118     \r
1119     if (EFI_ERROR (Status)) {\r
1120       goto ON_EXIT;\r
1121     }\r
1122     \r
1123     Status = gBS->SetTimer (\r
1124                    TimerToGetMap,\r
1125                    TimerRelative,\r
1126                    MultU64x32 (SEC_TO_NS, 5)\r
1127                    );\r
1128     \r
1129     if (EFI_ERROR (Status)) {\r
1130       goto ON_EXIT;\r
1131     }\r
1132 \r
1133     ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_WAIT_SET_DONE), gShellNetwork1HiiHandle);\r
1134     \r
1135     while (!mTimeout) {\r
1136       Ip4->Poll (Ip4);\r
1137   \r
1138       if (!EFI_ERROR (Ip4->GetModeData (Ip4, &Ip4Mode, NULL, NULL)) && \r
1139           Ip4Mode.IsConfigured) {       \r
1140         break;\r
1141       }\r
1142     }    \r
1143   }\r
1144 \r
1145   Status = Ip4->GetModeData (Ip4, &Ip4Mode, NULL, NULL);\r
1146 \r
1147   if ((Status == EFI_SUCCESS) && Ip4Mode.IsConfigured) {\r
1148     ShellPrintHiiEx(\r
1149       -1, \r
1150       -1, \r
1151       NULL,\r
1152       STRING_TOKEN (STR_IFCONFIG_SHOW_IP_ADDR), \r
1153       gShellNetwork1HiiHandle, \r
1154       L"Default",\r
1155       (UINTN)Ip4Mode.ConfigData.StationAddress.Addr[0],\r
1156       (UINTN)Ip4Mode.ConfigData.StationAddress.Addr[1],\r
1157       (UINTN)Ip4Mode.ConfigData.StationAddress.Addr[2],\r
1158       (UINTN)Ip4Mode.ConfigData.StationAddress.Addr[3]\r
1159       );\r
1160   }\r
1161   \r
1162 ON_EXIT: \r
1163 \r
1164   if (EFI_ERROR (Status)) {\r
1165     ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_GET_DEF_ADDR_FAIL), gShellNetwork1HiiHandle);\r
1166   }\r
1167 \r
1168   if (TimerToGetMap != NULL) {\r
1169     gBS->SetTimer (TimerToGetMap, TimerCancel, 0);\r
1170     gBS->CloseEvent (TimerToGetMap);\r
1171   }\r
1172 \r
1173   NetLibDestroyServiceChild (\r
1174     NicInfo->Handle,\r
1175     gImageHandle,\r
1176     &gEfiIp4ServiceBindingProtocolGuid,\r
1177     Ip4Handle\r
1178     );\r
1179   \r
1180   return Status;\r
1181 }\r
1182 \r
1183 /**\r
1184   Set the address for the nic specified by the params.\r
1185 \r
1186   @param[in] Argc       The count of the passed in Params.\r
1187   @param[in] Params     The command line arguments for the set operation.\r
1188 \r
1189   @retval EFI_SUCCESS   The address set operation is done.\r
1190   @return               Some error occurs.\r
1191 **/\r
1192 SHELL_STATUS\r
1193 EFIAPI\r
1194 IfconfigSetNicAddr (\r
1195   IN UINTN                      Argc,\r
1196   IN CONST CHAR16               *Params\r
1197   )\r
1198 {\r
1199   NIC_IP4_CONFIG_INFO           *Config;\r
1200   NIC_IP4_CONFIG_INFO           *OldConfig;\r
1201   EFI_IP_ADDRESS                Ip;\r
1202   EFI_IP_ADDRESS                Mask;\r
1203   EFI_IP_ADDRESS                Gateway;\r
1204   NIC_INFO                      *Info;\r
1205   BOOLEAN                       Permanent;\r
1206   SHELL_STATUS                  ShellStatus;\r
1207   CONST CHAR16                  *Walker;\r
1208   CHAR16                        *Temp;\r
1209   CONST CHAR16                  *DhcpTemp;\r
1210   CONST CHAR16                  *StaticTemp;\r
1211   CONST CHAR16                  *PermTemp;\r
1212   UINT32                        NetworkBytes1;\r
1213   UINT32                        NetworkBytes2;\r
1214   EFI_STATUS                    Status;\r
1215 \r
1216   Walker  = Params;\r
1217   Temp    = NULL;\r
1218   Temp    = StrnCatGrow(&Temp, NULL, Walker, StrStr(Walker, L" ")-Walker);\r
1219   Info    = IfconfigFindNicByName (Temp);\r
1220 \r
1221   if (Info == NULL) {\r
1222     ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_INTERFACE_NOT_FOUND), gShellNetwork1HiiHandle, Temp);\r
1223     return SHELL_NOT_FOUND;\r
1224   }\r
1225 \r
1226   Walker  += StrLen(Temp) + 1;\r
1227   FreePool(Temp);\r
1228   Temp = NULL;\r
1229   Temp    = StrnCatGrow(&Temp, NULL, Walker, StrStr(Walker, L" ")==NULL?0:StrStr(Walker, L" ")-Walker);\r
1230 \r
1231   Config = AllocateZeroPool (sizeof (NIC_IP4_CONFIG_INFO) + 2 * sizeof (EFI_IP4_ROUTE_TABLE));\r
1232   if (Config == NULL) {\r
1233     return SHELL_OUT_OF_RESOURCES;\r
1234   }\r
1235 \r
1236   Config->Ip4Info.RouteTable = (EFI_IP4_ROUTE_TABLE *) (Config + 1);\r
1237 \r
1238   OldConfig = Info->ConfigInfo;\r
1239   Permanent   = FALSE;\r
1240   ShellStatus = SHELL_INVALID_PARAMETER;\r
1241 \r
1242   DhcpTemp = DhcpString;\r
1243   StaticTemp = StaticString;\r
1244   \r
1245   if (StringNoCaseCompare(&Temp, &DhcpTemp) == 0) {\r
1246     //\r
1247     // Validate the parameter for DHCP, two valid forms: eth0 DHCP and eth0 DHCP perment\r
1248     //\r
1249     if ((Argc != 2) && (Argc!= 3)) {\r
1250       ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_GEN_PROBLEM_VAL), gShellNetwork1HiiHandle, Temp);\r
1251       ASSERT(ShellStatus == SHELL_INVALID_PARAMETER);\r
1252       goto ON_EXIT;\r
1253     }\r
1254 \r
1255     if (Argc == 3) {\r
1256       Walker  += StrLen(Temp) + 1;\r
1257       FreePool(Temp);\r
1258       Temp    = NULL;\r
1259       Temp    = StrnCatGrow(&Temp, NULL, Walker, 0);\r
1260 \r
1261       PermTemp = PermanentString;\r
1262       if (StringNoCaseCompare(&Temp, &PermTemp) != 0) {\r
1263         ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_GEN_PROBLEM_OP2), gShellNetwork1HiiHandle, Temp, PermanentString, L"Nothing");\r
1264         ASSERT(ShellStatus == SHELL_INVALID_PARAMETER);\r
1265         goto ON_EXIT;\r
1266       }\r
1267 \r
1268       Permanent = TRUE;\r
1269     }\r
1270 \r
1271     if ((OldConfig != NULL) && (OldConfig->Source == IP4_CONFIG_SOURCE_DHCP) &&\r
1272         (OldConfig->Perment == Permanent)) {\r
1273 \r
1274       ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_INTERFACE_CONFIGURED), gShellNetwork1HiiHandle, Info->Name);\r
1275       ShellStatus = SHELL_ALREADY_STARTED;\r
1276       goto ON_EXIT;\r
1277     }\r
1278 \r
1279     Config->Source = IP4_CONFIG_SOURCE_DHCP;\r
1280   } else if (StringNoCaseCompare(&Temp, &StaticTemp) == 0) {\r
1281     //\r
1282     // validate the parameter, two forms: eth0 static IP NETMASK GATEWAY and\r
1283     // eth0 static IP NETMASK GATEWAY perment\r
1284     //\r
1285     if ((Argc != 5) && (Argc != 6)) {\r
1286       ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_GEN_PROBLEM_VAL), gShellNetwork1HiiHandle, Temp);\r
1287       ASSERT(ShellStatus == SHELL_INVALID_PARAMETER);\r
1288       goto ON_EXIT;\r
1289     }\r
1290 \r
1291     Walker  += StrLen(Temp) + 1;\r
1292     FreePool(Temp);\r
1293     Temp    = NULL;\r
1294     Temp    = StrnCatGrow(&Temp, NULL, Walker, StrStr(Walker, L" ")-Walker);\r
1295 \r
1296     if (EFI_ERROR (NetLibStrToIp4 (Temp, &Ip.v4))) {\r
1297       ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_INVALID_IP_STR), gShellNetwork1HiiHandle, Temp);\r
1298       ASSERT(ShellStatus == SHELL_INVALID_PARAMETER);\r
1299       goto ON_EXIT;\r
1300     }\r
1301 \r
1302     Walker  += StrLen(Temp) + 1;\r
1303     FreePool(Temp);\r
1304     Temp    = NULL;\r
1305     Temp    = StrnCatGrow(&Temp, NULL, Walker, StrStr(Walker, L" ")-Walker);\r
1306     if (EFI_ERROR (NetLibStrToIp4 (Temp, &Mask.v4))) {\r
1307       ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_INVALID_IP_STR), gShellNetwork1HiiHandle, Temp);\r
1308       ASSERT(ShellStatus == SHELL_INVALID_PARAMETER);\r
1309       goto ON_EXIT;\r
1310     }\r
1311 \r
1312     Walker  += StrLen(Temp) + 1;\r
1313     FreePool(Temp);\r
1314     Temp    = NULL;\r
1315     if (Argc == 6) {\r
1316       Temp    = StrnCatGrow(&Temp, NULL, Walker, StrStr(Walker, L" ")-Walker);\r
1317     } else {\r
1318       Temp    = StrnCatGrow(&Temp, NULL, Walker, 0);\r
1319     }\r
1320     if (EFI_ERROR (NetLibStrToIp4 (Temp, &Gateway.v4))) {\r
1321       ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_INVALID_IP_STR), gShellNetwork1HiiHandle, Temp);\r
1322       ASSERT(ShellStatus == SHELL_INVALID_PARAMETER);\r
1323       goto ON_EXIT;\r
1324     }\r
1325 \r
1326     if (Argc == 6) {\r
1327       Walker  += StrLen(Temp) + 1;\r
1328       FreePool(Temp);\r
1329       Temp    = NULL;\r
1330       Temp    = StrnCatGrow(&Temp, NULL, Walker, 0);\r
1331 \r
1332       PermTemp = PermanentString;\r
1333       if (StringNoCaseCompare(&Temp, &PermTemp) != 0) {\r
1334         ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_GEN_PROBLEM_OP2), gShellNetwork1HiiHandle, Temp, PermanentString, L"Nothing");\r
1335         ASSERT(ShellStatus == SHELL_INVALID_PARAMETER);\r
1336         goto ON_EXIT;\r
1337       }\r
1338 \r
1339       Permanent = TRUE;\r
1340     }\r
1341 \r
1342     NetworkBytes1 = NTOHL (Ip.Addr[0]);\r
1343     NetworkBytes2 = NTOHL (Mask.Addr[0]);\r
1344     if ((Ip.Addr[0] == 0) || (Mask.Addr[0] == 0) ||\r
1345         !NetIp4IsUnicast (NetworkBytes1, NetworkBytes2)) {\r
1346 \r
1347       ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_INVALID_ADDR_PAIR), gShellNetwork1HiiHandle);\r
1348       ASSERT(ShellStatus == SHELL_INVALID_PARAMETER);\r
1349       goto ON_EXIT;\r
1350     }\r
1351 \r
1352     NetworkBytes1 = NTOHL (Gateway.Addr[0]);\r
1353     if (!IP4_NET_EQUAL (Ip.Addr[0], Gateway.Addr[0], Mask.Addr[0]) ||\r
1354         !NetIp4IsUnicast (NetworkBytes1, NetworkBytes2)) {\r
1355         \r
1356       ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_INVALID_GATEWAY), gShellNetwork1HiiHandle);\r
1357       ASSERT(ShellStatus == SHELL_INVALID_PARAMETER);\r
1358       goto ON_EXIT;\r
1359     }\r
1360 \r
1361     //\r
1362     // Set the configuration up, two route table entries are added:\r
1363     // one for the direct connected network, and another for the \r
1364     // default gateway. Remember, some structure members are cleared\r
1365     // by AllocateZeroPool\r
1366     //\r
1367     Config->Source = IP4_CONFIG_SOURCE_STATIC;\r
1368     Config->Ip4Info.RouteTableSize = 2;\r
1369 \r
1370     CopyMem (&Config->Ip4Info.StationAddress, &Ip.v4, sizeof (EFI_IPv4_ADDRESS));\r
1371     CopyMem (&Config->Ip4Info.SubnetMask, &Mask.v4, sizeof (EFI_IPv4_ADDRESS));\r
1372 \r
1373     Ip.Addr[0] = Ip.Addr[0] & Mask.Addr[0];\r
1374 \r
1375     CopyMem (&Config->Ip4Info.RouteTable[0].SubnetAddress, &Ip.v4, sizeof (EFI_IPv4_ADDRESS));\r
1376     CopyMem (&Config->Ip4Info.RouteTable[0].SubnetMask, &Mask.v4, sizeof (EFI_IPv4_ADDRESS));\r
1377     CopyMem (&Config->Ip4Info.RouteTable[1].GatewayAddress, &Gateway.v4, sizeof (EFI_IPv4_ADDRESS));\r
1378   } else {\r
1379     // neither static or DHCP.  error.\r
1380     ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_GEN_TOO_FEW), gShellNetwork1HiiHandle);\r
1381     ASSERT(ShellStatus == SHELL_INVALID_PARAMETER);\r
1382     goto ON_EXIT;\r
1383   }\r
1384 \r
1385   CopyMem (&Config->NicAddr, &Info->NicAddress, sizeof (NIC_ADDR));\r
1386   Config->Perment = Permanent;\r
1387 \r
1388   //\r
1389   // Use HII service to set NIC address\r
1390   //\r
1391   ShellStatus = IfconfigSetNicAddrByHii (Info, Config);\r
1392   if (ShellStatus != SHELL_SUCCESS) {\r
1393     ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_SET_FAIL), gShellNetwork1HiiHandle, ShellStatus^MAX_BIT);\r
1394     goto ON_EXIT;\r
1395   } \r
1396 \r
1397   Status = IfconfigStartIp4 (Info);\r
1398   if (EFI_ERROR(Status)) {\r
1399     ShellStatus = SHELL_ACCESS_DENIED;\r
1400   }\r
1401 \r
1402   if (ShellStatus != SHELL_SUCCESS) {\r
1403     ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_IP_CHILD_FAIL), gShellNetwork1HiiHandle, ShellStatus^MAX_BIT);\r
1404   }\r
1405   \r
1406 ON_EXIT:\r
1407   SHELL_FREE_NON_NULL(Config);\r
1408   \r
1409   return ShellStatus;\r
1410 }\r
1411 \r
1412 /**\r
1413   Show the address information for the nic specified.\r
1414 \r
1415   @param[in] Name   A pointer to the string containg the nic's name, if NULL, \r
1416                     all nics' information is shown.\r
1417 **/\r
1418 VOID\r
1419 EFIAPI\r
1420 IfconfigShowNicInfo (\r
1421   IN CONST CHAR16           *Name\r
1422   )\r
1423 {\r
1424   LIST_ENTRY                *Entry;\r
1425   LIST_ENTRY                *NextEntry;\r
1426   NIC_INFO                  *NicInfo;\r
1427   UINT32                    Index;\r
1428   EFI_IP4_IPCONFIG_DATA     *Ip4Config;\r
1429   EFI_IPv4_ADDRESS          Gateway;\r
1430   CONST CHAR16              *TempString;\r
1431 \r
1432   NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &NicInfoList) {\r
1433     NicInfo = BASE_CR (Entry, NIC_INFO, Link);\r
1434 \r
1435     TempString = (CHAR16*)NicInfo->Name;\r
1436     if ((Name != NULL) && (StringNoCaseCompare (&Name, &TempString) != 0)) {\r
1437       continue;\r
1438     }\r
1439 \r
1440     ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_NIC_NAME), gShellNetwork1HiiHandle, NicInfo->Name);\r
1441 \r
1442     ShellPrintHiiEx(\r
1443     -1,\r
1444     -1,\r
1445     NULL,\r
1446     STRING_TOKEN(STR_IFCONFIG_SHOW_MAC_ADDR), \r
1447     gShellNetwork1HiiHandle, \r
1448     (UINTN)NicInfo->NicAddress.MacAddr.Addr[0], \r
1449     (UINTN)NicInfo->NicAddress.MacAddr.Addr[1], \r
1450     (UINTN)NicInfo->NicAddress.MacAddr.Addr[2],\r
1451     (UINTN)NicInfo->NicAddress.MacAddr.Addr[3], \r
1452     (UINTN)NicInfo->NicAddress.MacAddr.Addr[4], \r
1453     (UINTN)NicInfo->NicAddress.MacAddr.Addr[5]\r
1454     );    \r
1455 \r
1456     Print (L"  Media State: %s\n", NicInfo->MediaPresent ? L"Media present" : L"Media disconnected");\r
1457 \r
1458     if (NicInfo->ConfigInfo == NULL) {\r
1459       ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_NIC_NOT_CONFIGURED), gShellNetwork1HiiHandle);\r
1460       continue;\r
1461     } \r
1462 \r
1463     if (NicInfo->ConfigInfo->Source == IP4_CONFIG_SOURCE_DHCP) {\r
1464       ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_CONFIG_SOURCE), gShellNetwork1HiiHandle, L"DHCP");\r
1465     } else if (NicInfo->ConfigInfo->Source == IP4_CONFIG_SOURCE_STATIC) {\r
1466       ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_CONFIG_SOURCE), gShellNetwork1HiiHandle, L"STATIC");\r
1467     } else {\r
1468       ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_CONFIG_SOURCE), gShellNetwork1HiiHandle, L"Unknown");\r
1469     }\r
1470 \r
1471     ShellPrintHiiEx(-1, -1, NULL,\r
1472       STRING_TOKEN (STR_IFCONFIG_PERMENT_STATUS),\r
1473       gShellNetwork1HiiHandle,\r
1474       (NicInfo->ConfigInfo->Perment? L"TRUE":L"FALSE")\r
1475       );\r
1476 \r
1477     Ip4Config = &NicInfo->ConfigInfo->Ip4Info;\r
1478 \r
1479     ShellPrintHiiEx(\r
1480       -1, \r
1481       -1, \r
1482       NULL,\r
1483       STRING_TOKEN (STR_IFCONFIG_SHOW_IP_ADDR), \r
1484       gShellNetwork1HiiHandle, \r
1485       L"IP address",\r
1486       (UINTN)Ip4Config->StationAddress.Addr[0],\r
1487       (UINTN)Ip4Config->StationAddress.Addr[1],\r
1488       (UINTN)Ip4Config->StationAddress.Addr[2],\r
1489       (UINTN)Ip4Config->StationAddress.Addr[3]\r
1490       );\r
1491     ShellPrintHiiEx(\r
1492       -1, \r
1493       -1, \r
1494       NULL,\r
1495       STRING_TOKEN (STR_IFCONFIG_SHOW_IP_ADDR), \r
1496       gShellNetwork1HiiHandle, \r
1497       L"Mask",\r
1498       (UINTN)Ip4Config->SubnetMask.Addr[0],\r
1499       (UINTN)Ip4Config->SubnetMask.Addr[1],\r
1500       (UINTN)Ip4Config->SubnetMask.Addr[2],\r
1501       (UINTN)Ip4Config->SubnetMask.Addr[3]\r
1502       );\r
1503 \r
1504     ZeroMem (&Gateway, sizeof (EFI_IPv4_ADDRESS));\r
1505     \r
1506     for (Index = 0; Index < Ip4Config->RouteTableSize; Index++) {\r
1507       if ((CompareMem (&Ip4Config->RouteTable[Index].SubnetAddress, &mZeroIp4Addr, sizeof (EFI_IPv4_ADDRESS)) == 0) &&\r
1508           (CompareMem (&Ip4Config->RouteTable[Index].SubnetMask   , &mZeroIp4Addr, sizeof (EFI_IPv4_ADDRESS)) == 0) ){\r
1509         CopyMem (&Gateway, &Ip4Config->RouteTable[Index].GatewayAddress, sizeof (EFI_IPv4_ADDRESS));\r
1510       }\r
1511     }\r
1512    \r
1513     ShellPrintHiiEx(\r
1514       -1, \r
1515       -1, \r
1516       NULL,\r
1517       STRING_TOKEN (STR_IFCONFIG_SHOW_IP_ADDR), \r
1518       gShellNetwork1HiiHandle, \r
1519       L"Gateway",\r
1520       (UINTN)Gateway.Addr[0],\r
1521       (UINTN)Gateway.Addr[1],\r
1522       (UINTN)Gateway.Addr[2],\r
1523       (UINTN)Gateway.Addr[3]\r
1524       );\r
1525 \r
1526     ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_ROUTES_SIZE), gShellNetwork1HiiHandle, Ip4Config->RouteTableSize);\r
1527 \r
1528     for (Index = 0; Index < Ip4Config->RouteTableSize; Index++) {\r
1529       ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_ROUTES_ENTRY_INDEX), gShellNetwork1HiiHandle, Index);\r
1530 \r
1531       ShellPrintHiiEx(\r
1532         -1, \r
1533         -1, \r
1534         NULL,\r
1535         STRING_TOKEN (STR_IFCONFIG_SHOW_IP_ADDR), \r
1536         gShellNetwork1HiiHandle, \r
1537         L"Subnet",\r
1538         (UINTN)Ip4Config->RouteTable[Index].SubnetAddress.Addr[0],\r
1539         (UINTN)Ip4Config->RouteTable[Index].SubnetAddress.Addr[1],\r
1540         (UINTN)Ip4Config->RouteTable[Index].SubnetAddress.Addr[2],\r
1541         (UINTN)Ip4Config->RouteTable[Index].SubnetAddress.Addr[3]\r
1542         );\r
1543 \r
1544       ShellPrintHiiEx(\r
1545         -1, \r
1546         -1, \r
1547         NULL,\r
1548         STRING_TOKEN (STR_IFCONFIG_SHOW_IP_ADDR), \r
1549         gShellNetwork1HiiHandle, \r
1550         L"Netmask",\r
1551         (UINTN)Ip4Config->RouteTable[Index].SubnetMask.Addr[0],\r
1552         (UINTN)Ip4Config->RouteTable[Index].SubnetMask.Addr[1],\r
1553         (UINTN)Ip4Config->RouteTable[Index].SubnetMask.Addr[2],\r
1554         (UINTN)Ip4Config->RouteTable[Index].SubnetMask.Addr[3]\r
1555         );\r
1556 \r
1557       ShellPrintHiiEx(\r
1558         -1, \r
1559         -1, \r
1560         NULL,\r
1561         STRING_TOKEN (STR_IFCONFIG_SHOW_IP_ADDR), \r
1562         gShellNetwork1HiiHandle, \r
1563         L"Gateway",\r
1564         (UINTN)Ip4Config->RouteTable[Index].GatewayAddress.Addr[0],\r
1565         (UINTN)Ip4Config->RouteTable[Index].GatewayAddress.Addr[1],\r
1566         (UINTN)Ip4Config->RouteTable[Index].GatewayAddress.Addr[2],\r
1567         (UINTN)Ip4Config->RouteTable[Index].GatewayAddress.Addr[3]\r
1568         );\r
1569     }\r
1570   }\r
1571 \r
1572   return ;\r
1573 }\r
1574 \r
1575 /**\r
1576   Clear address configuration for the nic specified.\r
1577 \r
1578   @param[in] Name     A pointer to the string containg the nic's name, \r
1579                       if NULL, all nics address configurations are cleared.\r
1580 \r
1581   @retval EFI_SUCCESS The address configuration is cleared.\r
1582   @return             Some error occurs.\r
1583 **/\r
1584 EFI_STATUS\r
1585 EFIAPI\r
1586 IfconfigClearNicAddr (\r
1587   IN CONST CHAR16                     *Name\r
1588   )\r
1589 {\r
1590   LIST_ENTRY                    *Entry;\r
1591   LIST_ENTRY                    *NextEntry;\r
1592   NIC_INFO                      *Info;\r
1593   EFI_STATUS                    Status;\r
1594   \r
1595   NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &NicInfoList) {\r
1596     Info = BASE_CR (Entry, NIC_INFO, Link);\r
1597 \r
1598     if ((Name != NULL) && (StrCmp (Name, Info->Name) != 0)) {\r
1599       continue;\r
1600     }\r
1601 \r
1602 //    if (Info->NicIp4Config == NULL) { \r
1603       Status = IfconfigSetNicAddrByHii (Info, NULL);\r
1604 //    } else {\r
1605 //      Status = Info->NicIp4Config->SetInfo (Info->NicIp4Config, NULL, TRUE);\r
1606 //    }\r
1607 \r
1608     if (EFI_ERROR (Status)) {\r
1609       return Status;\r
1610     }\r
1611   }\r
1612 \r
1613   return EFI_SUCCESS;\r
1614   \r
1615 }\r
1616 \r
1617 /**\r
1618   Function for 'ifconfig' command.\r
1619 \r
1620   @param[in] ImageHandle  Handle to the Image (NULL if Internal).\r
1621   @param[in] SystemTable  Pointer to the System Table (NULL if Internal).\r
1622 **/\r
1623 SHELL_STATUS\r
1624 EFIAPI\r
1625 ShellCommandRunIfconfig (\r
1626   IN EFI_HANDLE        ImageHandle,\r
1627   IN EFI_SYSTEM_TABLE  *SystemTable\r
1628   )\r
1629 {\r
1630   EFI_STATUS          Status;\r
1631   LIST_ENTRY          *Package;\r
1632   CHAR16              *ProblemParam;\r
1633   SHELL_STATUS        ShellStatus;\r
1634   BOOLEAN             ListOperation;\r
1635   BOOLEAN             ClearOperation;\r
1636   BOOLEAN             SetOperation;\r
1637   CONST CHAR16        *Item;\r
1638   LIST_ENTRY          *Entry;\r
1639   NIC_INFO            *Info;\r
1640 \r
1641   InitializeListHead (&NicInfoList);\r
1642   Status = EFI_INVALID_PARAMETER;\r
1643   ShellStatus = SHELL_SUCCESS;\r
1644 \r
1645   //\r
1646   // initialize the shell lib (we must be in non-auto-init...)\r
1647   //\r
1648   Status = ShellInitialize();\r
1649   ASSERT_EFI_ERROR(Status);\r
1650 \r
1651   //\r
1652   // parse the command line\r
1653   //\r
1654   Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);\r
1655   if (EFI_ERROR(Status)) {\r
1656     if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {\r
1657       ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellNetwork1HiiHandle, ProblemParam);\r
1658       FreePool(ProblemParam);\r
1659       ShellStatus = SHELL_INVALID_PARAMETER;\r
1660     } else {\r
1661       ASSERT(FALSE);\r
1662     }\r
1663 \r
1664     goto Done;\r
1665   }\r
1666 \r
1667   ClearOperation = ShellCommandLineGetFlag(Package, L"-c");\r
1668   ListOperation  = ShellCommandLineGetFlag(Package, L"-l");\r
1669   SetOperation   = ShellCommandLineGetFlag(Package, L"-s");\r
1670 \r
1671   if ((ClearOperation && ListOperation)\r
1672     ||(SetOperation   && ListOperation)\r
1673     ||(ClearOperation && SetOperation)\r
1674     ) {\r
1675     ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_CON), gShellNetwork1HiiHandle);\r
1676     ShellStatus = SHELL_INVALID_PARAMETER;\r
1677     goto Done;\r
1678   } else if (!ClearOperation && !ListOperation && !SetOperation) {\r
1679     ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellNetwork1HiiHandle);\r
1680     ShellStatus = SHELL_INVALID_PARAMETER;\r
1681     goto Done;\r
1682   }\r
1683     \r
1684     \r
1685   Status = IfconfigGetAllNicInfoByHii ();\r
1686   if (EFI_ERROR (Status)) {\r
1687     if (mIp4ConfigExist) {\r
1688       ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_GET_NIC_FAIL), gShellNetwork1HiiHandle, Status);\r
1689     } else {\r
1690       ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROTOCOL_NF), gShellNetwork1HiiHandle, L"gEfiIp4ConfigProtocolGuid", &gEfiIp4ConfigProtocolGuid);\r
1691     }\r
1692 \r
1693     return SHELL_NOT_FOUND;\r
1694   }\r
1695 \r
1696   if (ListOperation) {\r
1697     Item = ShellCommandLineGetValue (Package, L"-l");\r
1698 \r
1699     if (Item != NULL && CountSubItems(Item) > 1) {\r
1700       ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM_VAL), gShellNetwork1HiiHandle, L"-l");\r
1701       ShellStatus = SHELL_INVALID_PARAMETER;\r
1702       goto Done;\r
1703     } \r
1704     \r
1705     //\r
1706     // Show the configuration.\r
1707     //\r
1708     IfconfigShowNicInfo (Item);\r
1709   } else if (SetOperation) {\r
1710     Item = ShellCommandLineGetValue (Package, L"-s");\r
1711 \r
1712     //\r
1713     // The correct command line arguments for setting address are:\r
1714     // IfConfig -s eth0 DHCP [perment]\r
1715     // IfConfig -s eth0 static ip netmask gateway [perment]\r
1716     //\r
1717     if (Item == NULL || (CountSubItems(Item) < 2) || (CountSubItems(Item) > 6) || (CountSubItems(Item) == 4)) {\r
1718       ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_GEN_PROBLEM_VAL), gShellNetwork1HiiHandle, L"-s");\r
1719       ShellStatus = SHELL_INVALID_PARAMETER;\r
1720       goto Done;\r
1721     }\r
1722 \r
1723     ShellStatus = IfconfigSetNicAddr (CountSubItems(Item), Item);\r
1724   } else if (ClearOperation) {\r
1725     Item = ShellCommandLineGetValue (Package, L"-c");\r
1726 \r
1727     if (Item != NULL && CountSubItems(Item) > 1) {\r
1728       ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM_VAL), gShellNetwork1HiiHandle, L"-c");\r
1729       ShellStatus = SHELL_INVALID_PARAMETER;\r
1730       goto Done;\r
1731     }\r
1732 \r
1733     IfconfigClearNicAddr (Item);\r
1734   } else {\r
1735     ASSERT(FALSE);\r
1736   }\r
1737 \r
1738 Done:\r
1739   while (!IsListEmpty (&NicInfoList)) {\r
1740     Entry = NicInfoList.ForwardLink;\r
1741     Info  = BASE_CR (Entry, NIC_INFO, Link);\r
1742 \r
1743     RemoveEntryList (Entry);\r
1744 \r
1745     if (Info->ConfigInfo != NULL) {\r
1746       FreePool (Info->ConfigInfo);\r
1747     }\r
1748 \r
1749     FreePool (Info);\r
1750   }\r
1751 \r
1752   if (Package != NULL) {\r
1753     ShellCommandLineFreeVarList(Package);\r
1754   }\r
1755 \r
1756   return (ShellStatus);\r
1757 }\r