Comment's added and fixed.
[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     ShellStatus = SHELL_OUT_OF_RESOURCES;\r
785     goto ON_EXIT;\r
786   }\r
787   ConfigResp = AllocateZeroPool ((Length + NIC_ITEM_CONFIG_SIZE * 2 + 100) * sizeof (CHAR16));\r
788   if (ConfigResp == NULL) {\r
789     ShellStatus = SHELL_OUT_OF_RESOURCES;\r
790     goto ON_EXIT;\r
791   }\r
792   if (ConfigHdr != NULL) {\r
793     StrCpy (ConfigResp, ConfigHdr);\r
794   }\r
795 \r
796   NicConfig = AllocateZeroPool (NIC_ITEM_CONFIG_SIZE);\r
797   if (NicConfig == NULL) {\r
798     ShellStatus = SHELL_OUT_OF_RESOURCES;\r
799     goto ON_EXIT;\r
800   }\r
801 \r
802   if (Config != NULL) {\r
803     CopyMem (NicConfig, Config, sizeof (NIC_IP4_CONFIG_INFO) + sizeof (EFI_IP4_ROUTE_TABLE) * Config->Ip4Info.RouteTableSize);\r
804   }\r
805 \r
806   //\r
807   // Append OFFSET/WIDTH pair\r
808   //\r
809   String = ConfigResp + Length;\r
810   Offset = 0;\r
811   AppendOffsetWidthValue (String, Offset, NIC_ITEM_CONFIG_SIZE, NULL);\r
812 \r
813   //\r
814   // Call HII helper function to generate configuration string\r
815   //\r
816   Status = mHiiConfigRouting->BlockToConfig (\r
817                                 mHiiConfigRouting,\r
818                                 ConfigResp,\r
819                                 (UINT8 *) NicConfig,\r
820                                 NIC_ITEM_CONFIG_SIZE,\r
821                                 &AccessResults,\r
822                                 &AccessProgress\r
823                                 );\r
824   if (EFI_ERROR (Status)) {\r
825     ShellStatus = SHELL_NOT_FOUND;\r
826     goto ON_EXIT;\r
827   }\r
828 \r
829   //\r
830   // Set IP setting by HII servie\r
831   //\r
832   Status = mHiiConfigRouting->RouteConfig (\r
833                                 mHiiConfigRouting,\r
834                                 AccessResults,\r
835                                 &AccessProgress\r
836                                 );\r
837   if (EFI_ERROR(Status)) {\r
838     ShellStatus = SHELL_ACCESS_DENIED;\r
839   }\r
840 \r
841 ON_EXIT:\r
842   SHELL_FREE_NON_NULL(AccessResults);\r
843   SHELL_FREE_NON_NULL(NicConfig);\r
844   SHELL_FREE_NON_NULL(ConfigResp);\r
845   SHELL_FREE_NON_NULL(ConfigHdr);\r
846 \r
847   return ShellStatus;\r
848 }\r
849 \r
850 /**\r
851   The callback function for the Arp address resolved event.\r
852 \r
853   @param[in] Event    The event this function is registered to.\r
854   @param[in] Context  The context registered to the event.\r
855 **/\r
856 VOID\r
857 EFIAPI\r
858 IfconfigOnArpResolved (\r
859   IN EFI_EVENT                  Event,\r
860   IN VOID                       *Context\r
861   )\r
862 {\r
863   ARP_REQUEST                   *Request;\r
864   UINT8                         Index;\r
865 \r
866   Request = (ARP_REQUEST *) Context;\r
867   ASSERT (Request != NULL);\r
868 \r
869   Request->Duplicate = FALSE;\r
870   \r
871   if (0 == CompareMem (&Request->LocalMac, &Request->DestMac, Request->MacLen)) {\r
872     ShellPrintHiiEx(\r
873       -1, \r
874       -1, \r
875       NULL,\r
876       STRING_TOKEN (STR_IFCONFIG_SHOW_IP_ADDR), \r
877       gShellNetwork1HiiHandle, \r
878       L"Already Configured",\r
879       (UINTN)Request->DestIp.v4.Addr[0],\r
880       (UINTN)Request->DestIp.v4.Addr[1],\r
881       (UINTN)Request->DestIp.v4.Addr[2],\r
882       (UINTN)Request->DestIp.v4.Addr[3]\r
883       );\r
884     ArpResolved = TRUE;\r
885     return;\r
886   }\r
887   \r
888   for (Index = 0; Index < Request->MacLen; Index++) {\r
889     if (Request->DestMac.Addr[Index] != 0) {\r
890       Request->Duplicate = TRUE;\r
891     }\r
892   }\r
893 \r
894   if (Request->Duplicate) {\r
895     ShellPrintHiiEx(\r
896     -1,\r
897     -1,\r
898     NULL,\r
899     STRING_TOKEN(STR_IFCONFIG_CONF_IP_ADDR), \r
900     gShellNetwork1HiiHandle, \r
901     (UINTN)Request->DestMac.Addr[0], \r
902     (UINTN)Request->DestMac.Addr[1], \r
903     (UINTN)Request->DestMac.Addr[2],\r
904     (UINTN)Request->DestMac.Addr[3], \r
905     (UINTN)Request->DestMac.Addr[4], \r
906     (UINTN)Request->DestMac.Addr[5]\r
907     );    \r
908   }\r
909 \r
910   ArpResolved = TRUE;\r
911   return ;\r
912 }\r
913 \r
914 /**\r
915   Check whether the address to be configured conflicts with other hosts.\r
916 \r
917   @param[in] NicInfo    The pointer to the NIC_INFO of the Nic to be configured.\r
918   @param[in] IpAddr     The IPv4 address to be configured to the Nic.\r
919 \r
920   @return TRUE      Some other host already uses the IpAddr.\r
921   @return FALSE     The address is unused.\r
922 **/\r
923 BOOLEAN\r
924 EFIAPI\r
925 IfconfigIsIpDuplicate (\r
926   IN  NIC_INFO                  *NicInfo,\r
927   IN  IP4_ADDR                  IpAddr\r
928   )\r
929 {\r
930   EFI_ARP_PROTOCOL              *Arp;\r
931   EFI_ARP_CONFIG_DATA           ArpCfgData;\r
932   EFI_HANDLE                    ArpHandle;\r
933   ARP_REQUEST                   Request;\r
934   EFI_STATUS                    Status;\r
935 \r
936   Arp           = NULL;\r
937   ArpHandle     = NULL;\r
938   ZeroMem (&Request, sizeof (ARP_REQUEST));\r
939 \r
940   Status = NetLibCreateServiceChild (\r
941              NicInfo->Handle,\r
942              gImageHandle, \r
943              &gEfiArpServiceBindingProtocolGuid,\r
944              &ArpHandle\r
945              );\r
946 \r
947   if (EFI_ERROR (Status)) {\r
948     return FALSE;\r
949   }\r
950 \r
951   Status = gBS->OpenProtocol (\r
952                  ArpHandle,\r
953                  &gEfiArpProtocolGuid,\r
954                  (VOID**)&Arp,\r
955                  gImageHandle,\r
956                  ArpHandle,\r
957                  EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
958                  );\r
959 \r
960   if (EFI_ERROR (Status)) {\r
961     goto ON_EXIT;\r
962   }\r
963 \r
964   //\r
965   // Set up the Arp requests\r
966   //\r
967   EFI_IP4_TO_U32 (Request.DestIp.v4)  = IpAddr;\r
968   EFI_IP4_TO_U32 (Request.LocalIp.v4) = 0xffffffff;\r
969   Request.LocalMac                    = NicInfo->NicAddress.MacAddr;\r
970   Request.MacLen                      = NicInfo->NicAddress.Len;\r
971   \r
972   Status = gBS->CreateEvent (\r
973                  EVT_NOTIFY_SIGNAL,\r
974                  TPL_CALLBACK,\r
975                  IfconfigOnArpResolved,\r
976                  (VOID *) &Request,\r
977                  &Request.OnResolved\r
978                  );\r
979   \r
980   if (EFI_ERROR (Status)) {\r
981     goto ON_EXIT;\r
982   }\r
983   \r
984   ArpCfgData.SwAddressType    = 0x0800;\r
985   ArpCfgData.SwAddressLength  = 4;\r
986   ArpCfgData.StationAddress   = &Request.LocalIp;\r
987   ArpCfgData.EntryTimeOut     = 0;\r
988   ArpCfgData.RetryCount       = 3;\r
989   ArpCfgData.RetryTimeOut     = 0;\r
990   \r
991   Status = Arp->Configure (Arp, &ArpCfgData);\r
992   \r
993   if (EFI_ERROR (Status)) {\r
994     goto ON_EXIT;\r
995   }\r
996 \r
997   Status = Arp->Request (\r
998                   Arp,\r
999                   &Request.DestIp,\r
1000                   Request.OnResolved,\r
1001                   &Request.DestMac\r
1002                   );\r
1003   \r
1004   if (EFI_ERROR (Status) && (Status != EFI_NOT_READY)) {\r
1005     goto ON_EXIT;\r
1006   }\r
1007 \r
1008   while (!ArpResolved) {\r
1009     \r
1010   }\r
1011 \r
1012 ON_EXIT:\r
1013   if (Request.OnResolved != NULL) {\r
1014     gBS->CloseEvent (Request.OnResolved);\r
1015   }\r
1016 \r
1017   NetLibDestroyServiceChild (\r
1018     NicInfo->Handle, \r
1019     gImageHandle, \r
1020     &gEfiArpServiceBindingProtocolGuid, \r
1021     ArpHandle\r
1022     );\r
1023 \r
1024   return Request.Duplicate;\r
1025 }\r
1026 \r
1027 /**\r
1028   The callback function for the timer event used to get map.\r
1029 \r
1030   @param[in] Event    The event this function is registered to.\r
1031   @param[in] Context  The context registered to the event.\r
1032 **/\r
1033 VOID\r
1034 EFIAPI\r
1035 TimeoutToGetMap (\r
1036   IN EFI_EVENT      Event,\r
1037   IN VOID           *Context\r
1038   )\r
1039 {\r
1040   mTimeout = TRUE;\r
1041   return ;\r
1042 }\r
1043 \r
1044 /**\r
1045   Create an IP child, use it to start the auto configuration, then destory it.\r
1046 \r
1047   @param[in] NicInfo    The pointer to the NIC_INFO of the Nic to be configured.\r
1048 \r
1049   @retval EFI_SUCCESS         The configuration is done.\r
1050 **/\r
1051 EFI_STATUS\r
1052 EFIAPI\r
1053 IfconfigStartIp4(\r
1054   IN NIC_INFO                   *NicInfo\r
1055   )\r
1056 {\r
1057   EFI_IP4_PROTOCOL              *Ip4;\r
1058   EFI_HANDLE                    Ip4Handle;\r
1059   EFI_HANDLE                    TimerToGetMap;\r
1060   EFI_IP4_CONFIG_DATA           Ip4ConfigData;\r
1061   EFI_IP4_MODE_DATA             Ip4Mode;\r
1062   EFI_STATUS                    Status;\r
1063 \r
1064   //\r
1065   // Get the Ip4ServiceBinding Protocol\r
1066   //\r
1067   Ip4Handle     = NULL;\r
1068   Ip4           = NULL;\r
1069   TimerToGetMap = NULL;\r
1070 \r
1071   ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_START_SET_ADDR), gShellNetwork1HiiHandle);\r
1072 \r
1073   Status = NetLibCreateServiceChild (\r
1074              NicInfo->Handle,\r
1075              gImageHandle,\r
1076              &gEfiIp4ServiceBindingProtocolGuid,\r
1077              &Ip4Handle\r
1078              );\r
1079 \r
1080   if (EFI_ERROR (Status)) {\r
1081     return Status;\r
1082   }\r
1083 \r
1084   Status = gBS->OpenProtocol (\r
1085                  Ip4Handle,\r
1086                  &gEfiIp4ProtocolGuid,\r
1087                  (VOID **) &Ip4,\r
1088                  NicInfo->Handle,\r
1089                  gImageHandle,\r
1090                  EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
1091                  );\r
1092 \r
1093   if (EFI_ERROR (Status)) {\r
1094     goto ON_EXIT;\r
1095   }\r
1096 \r
1097   Ip4ConfigData.DefaultProtocol          = EFI_IP_PROTO_ICMP;\r
1098   Ip4ConfigData.AcceptAnyProtocol        = FALSE;\r
1099   Ip4ConfigData.AcceptIcmpErrors         = FALSE;\r
1100   Ip4ConfigData.AcceptBroadcast          = FALSE;\r
1101   Ip4ConfigData.AcceptPromiscuous        = FALSE;\r
1102   Ip4ConfigData.UseDefaultAddress        = TRUE;\r
1103   ZeroMem (&Ip4ConfigData.StationAddress, sizeof (EFI_IPv4_ADDRESS));\r
1104   ZeroMem (&Ip4ConfigData.SubnetMask, sizeof (EFI_IPv4_ADDRESS));\r
1105   Ip4ConfigData.TypeOfService            = 0;\r
1106   Ip4ConfigData.TimeToLive               = 1;\r
1107   Ip4ConfigData.DoNotFragment            = FALSE;\r
1108   Ip4ConfigData.RawData                  = FALSE;\r
1109   Ip4ConfigData.ReceiveTimeout           = 0;\r
1110   Ip4ConfigData.TransmitTimeout          = 0;\r
1111 \r
1112   Status = Ip4->Configure (Ip4, &Ip4ConfigData);\r
1113 \r
1114   if (Status == EFI_NO_MAPPING) {\r
1115     mTimeout = FALSE;\r
1116     Status  = gBS->CreateEvent (\r
1117                     EVT_NOTIFY_SIGNAL | EVT_TIMER,\r
1118                     TPL_CALLBACK - 1,\r
1119                     TimeoutToGetMap,\r
1120                     NULL,\r
1121                     &TimerToGetMap\r
1122                     );\r
1123     \r
1124     if (EFI_ERROR (Status)) {\r
1125       goto ON_EXIT;\r
1126     }\r
1127     \r
1128     Status = gBS->SetTimer (\r
1129                    TimerToGetMap,\r
1130                    TimerRelative,\r
1131                    MultU64x32 (SEC_TO_NS, 5)\r
1132                    );\r
1133     \r
1134     if (EFI_ERROR (Status)) {\r
1135       goto ON_EXIT;\r
1136     }\r
1137 \r
1138     ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_WAIT_SET_DONE), gShellNetwork1HiiHandle);\r
1139     \r
1140     while (!mTimeout) {\r
1141       Ip4->Poll (Ip4);\r
1142   \r
1143       if (!EFI_ERROR (Ip4->GetModeData (Ip4, &Ip4Mode, NULL, NULL)) && \r
1144           Ip4Mode.IsConfigured) {       \r
1145         break;\r
1146       }\r
1147     }    \r
1148   }\r
1149 \r
1150   Status = Ip4->GetModeData (Ip4, &Ip4Mode, NULL, NULL);\r
1151 \r
1152   if ((Status == EFI_SUCCESS) && Ip4Mode.IsConfigured) {\r
1153     ShellPrintHiiEx(\r
1154       -1, \r
1155       -1, \r
1156       NULL,\r
1157       STRING_TOKEN (STR_IFCONFIG_SHOW_IP_ADDR), \r
1158       gShellNetwork1HiiHandle, \r
1159       L"Default",\r
1160       (UINTN)Ip4Mode.ConfigData.StationAddress.Addr[0],\r
1161       (UINTN)Ip4Mode.ConfigData.StationAddress.Addr[1],\r
1162       (UINTN)Ip4Mode.ConfigData.StationAddress.Addr[2],\r
1163       (UINTN)Ip4Mode.ConfigData.StationAddress.Addr[3]\r
1164       );\r
1165   }\r
1166   \r
1167 ON_EXIT: \r
1168 \r
1169   if (EFI_ERROR (Status)) {\r
1170     ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_GET_DEF_ADDR_FAIL), gShellNetwork1HiiHandle);\r
1171   }\r
1172 \r
1173   if (TimerToGetMap != NULL) {\r
1174     gBS->SetTimer (TimerToGetMap, TimerCancel, 0);\r
1175     gBS->CloseEvent (TimerToGetMap);\r
1176   }\r
1177 \r
1178   NetLibDestroyServiceChild (\r
1179     NicInfo->Handle,\r
1180     gImageHandle,\r
1181     &gEfiIp4ServiceBindingProtocolGuid,\r
1182     Ip4Handle\r
1183     );\r
1184   \r
1185   return Status;\r
1186 }\r
1187 \r
1188 /**\r
1189   Set the address for the nic specified by the params.\r
1190 \r
1191   @param[in] Argc       The count of the passed in Params.\r
1192   @param[in] Params     The command line arguments for the set operation.\r
1193 \r
1194   @retval EFI_SUCCESS   The address set operation is done.\r
1195   @return               Some error occurs.\r
1196 **/\r
1197 SHELL_STATUS\r
1198 EFIAPI\r
1199 IfconfigSetNicAddr (\r
1200   IN UINTN                      Argc,\r
1201   IN CONST CHAR16               *Params\r
1202   )\r
1203 {\r
1204   NIC_IP4_CONFIG_INFO           *Config;\r
1205   NIC_IP4_CONFIG_INFO           *OldConfig;\r
1206   EFI_IP_ADDRESS                Ip;\r
1207   EFI_IP_ADDRESS                Mask;\r
1208   EFI_IP_ADDRESS                Gateway;\r
1209   NIC_INFO                      *Info;\r
1210   BOOLEAN                       Permanent;\r
1211   SHELL_STATUS                  ShellStatus;\r
1212   CONST CHAR16                  *Walker;\r
1213   CHAR16                        *Temp;\r
1214   CONST CHAR16                  *DhcpTemp;\r
1215   CONST CHAR16                  *StaticTemp;\r
1216   CONST CHAR16                  *PermTemp;\r
1217   UINT32                        NetworkBytes1;\r
1218   UINT32                        NetworkBytes2;\r
1219   EFI_STATUS                    Status;\r
1220 \r
1221   Walker  = Params;\r
1222   Temp    = NULL;\r
1223   Temp    = StrnCatGrow(&Temp, NULL, Walker, StrStr(Walker, L" ")-Walker);\r
1224   Info    = IfconfigFindNicByName (Temp);\r
1225 \r
1226   if (Info == NULL) {\r
1227     ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_INTERFACE_NOT_FOUND), gShellNetwork1HiiHandle, Temp);\r
1228     return SHELL_NOT_FOUND;\r
1229   }\r
1230 \r
1231   Walker  += StrLen(Temp) + 1;\r
1232   FreePool(Temp);\r
1233   Temp = NULL;\r
1234   Temp    = StrnCatGrow(&Temp, NULL, Walker, StrStr(Walker, L" ")==NULL?0:StrStr(Walker, L" ")-Walker);\r
1235 \r
1236   Config = AllocateZeroPool (sizeof (NIC_IP4_CONFIG_INFO) + 2 * sizeof (EFI_IP4_ROUTE_TABLE));\r
1237   if (Config == NULL) {\r
1238     return SHELL_OUT_OF_RESOURCES;\r
1239   }\r
1240 \r
1241   Config->Ip4Info.RouteTable = (EFI_IP4_ROUTE_TABLE *) (Config + 1);\r
1242 \r
1243   OldConfig = Info->ConfigInfo;\r
1244   Permanent   = FALSE;\r
1245   ShellStatus = SHELL_INVALID_PARAMETER;\r
1246 \r
1247   DhcpTemp = DhcpString;\r
1248   StaticTemp = StaticString;\r
1249   \r
1250   if (StringNoCaseCompare(&Temp, &DhcpTemp) == 0) {\r
1251     //\r
1252     // Validate the parameter for DHCP, two valid forms: eth0 DHCP and eth0 DHCP perment\r
1253     //\r
1254     if ((Argc != 2) && (Argc!= 3)) {\r
1255       ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_GEN_PROBLEM_VAL), gShellNetwork1HiiHandle, Temp);\r
1256       ASSERT(ShellStatus == SHELL_INVALID_PARAMETER);\r
1257       goto ON_EXIT;\r
1258     }\r
1259 \r
1260     if (Argc == 3) {\r
1261       Walker  += StrLen(Temp) + 1;\r
1262       FreePool(Temp);\r
1263       Temp    = NULL;\r
1264       Temp    = StrnCatGrow(&Temp, NULL, Walker, 0);\r
1265 \r
1266       PermTemp = PermanentString;\r
1267       if (StringNoCaseCompare(&Temp, &PermTemp) != 0) {\r
1268         ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_GEN_PROBLEM_OP2), gShellNetwork1HiiHandle, Temp, PermanentString, L"Nothing");\r
1269         ASSERT(ShellStatus == SHELL_INVALID_PARAMETER);\r
1270         goto ON_EXIT;\r
1271       }\r
1272 \r
1273       Permanent = TRUE;\r
1274     }\r
1275 \r
1276     if ((OldConfig != NULL) && (OldConfig->Source == IP4_CONFIG_SOURCE_DHCP) &&\r
1277         (OldConfig->Perment == Permanent)) {\r
1278 \r
1279       ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_INTERFACE_CONFIGURED), gShellNetwork1HiiHandle, Info->Name);\r
1280       ShellStatus = SHELL_ALREADY_STARTED;\r
1281       goto ON_EXIT;\r
1282     }\r
1283 \r
1284     Config->Source = IP4_CONFIG_SOURCE_DHCP;\r
1285   } else if (StringNoCaseCompare(&Temp, &StaticTemp) == 0) {\r
1286     //\r
1287     // validate the parameter, two forms: eth0 static IP NETMASK GATEWAY and\r
1288     // eth0 static IP NETMASK GATEWAY perment\r
1289     //\r
1290     if ((Argc != 5) && (Argc != 6)) {\r
1291       ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_GEN_PROBLEM_VAL), gShellNetwork1HiiHandle, Temp);\r
1292       ASSERT(ShellStatus == SHELL_INVALID_PARAMETER);\r
1293       goto ON_EXIT;\r
1294     }\r
1295 \r
1296     Walker  += StrLen(Temp) + 1;\r
1297     FreePool(Temp);\r
1298     Temp    = NULL;\r
1299     Temp    = StrnCatGrow(&Temp, NULL, Walker, StrStr(Walker, L" ")-Walker);\r
1300 \r
1301     if (EFI_ERROR (NetLibStrToIp4 (Temp, &Ip.v4))) {\r
1302       ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_INVALID_IP_STR), gShellNetwork1HiiHandle, Temp);\r
1303       ASSERT(ShellStatus == SHELL_INVALID_PARAMETER);\r
1304       goto ON_EXIT;\r
1305     }\r
1306 \r
1307     Walker  += StrLen(Temp) + 1;\r
1308     FreePool(Temp);\r
1309     Temp    = NULL;\r
1310     Temp    = StrnCatGrow(&Temp, NULL, Walker, StrStr(Walker, L" ")-Walker);\r
1311     if (EFI_ERROR (NetLibStrToIp4 (Temp, &Mask.v4))) {\r
1312       ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_INVALID_IP_STR), gShellNetwork1HiiHandle, Temp);\r
1313       ASSERT(ShellStatus == SHELL_INVALID_PARAMETER);\r
1314       goto ON_EXIT;\r
1315     }\r
1316 \r
1317     Walker  += StrLen(Temp) + 1;\r
1318     FreePool(Temp);\r
1319     Temp    = NULL;\r
1320     if (Argc == 6) {\r
1321       Temp    = StrnCatGrow(&Temp, NULL, Walker, StrStr(Walker, L" ")-Walker);\r
1322     } else {\r
1323       Temp    = StrnCatGrow(&Temp, NULL, Walker, 0);\r
1324     }\r
1325     if (EFI_ERROR (NetLibStrToIp4 (Temp, &Gateway.v4))) {\r
1326       ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_INVALID_IP_STR), gShellNetwork1HiiHandle, Temp);\r
1327       ASSERT(ShellStatus == SHELL_INVALID_PARAMETER);\r
1328       goto ON_EXIT;\r
1329     }\r
1330 \r
1331     if (Argc == 6) {\r
1332       Walker  += StrLen(Temp) + 1;\r
1333       FreePool(Temp);\r
1334       Temp    = NULL;\r
1335       Temp    = StrnCatGrow(&Temp, NULL, Walker, 0);\r
1336 \r
1337       PermTemp = PermanentString;\r
1338       if (StringNoCaseCompare(&Temp, &PermTemp) != 0) {\r
1339         ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_GEN_PROBLEM_OP2), gShellNetwork1HiiHandle, Temp, PermanentString, L"Nothing");\r
1340         ASSERT(ShellStatus == SHELL_INVALID_PARAMETER);\r
1341         goto ON_EXIT;\r
1342       }\r
1343 \r
1344       Permanent = TRUE;\r
1345     }\r
1346 \r
1347     NetworkBytes1 = NTOHL (Ip.Addr[0]);\r
1348     NetworkBytes2 = NTOHL (Mask.Addr[0]);\r
1349     if ((Ip.Addr[0] == 0) || (Mask.Addr[0] == 0) ||\r
1350         !NetIp4IsUnicast (NetworkBytes1, NetworkBytes2)) {\r
1351 \r
1352       ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_INVALID_ADDR_PAIR), gShellNetwork1HiiHandle);\r
1353       ASSERT(ShellStatus == SHELL_INVALID_PARAMETER);\r
1354       goto ON_EXIT;\r
1355     }\r
1356 \r
1357     NetworkBytes1 = NTOHL (Gateway.Addr[0]);\r
1358     if (!IP4_NET_EQUAL (Ip.Addr[0], Gateway.Addr[0], Mask.Addr[0]) ||\r
1359         !NetIp4IsUnicast (NetworkBytes1, NetworkBytes2)) {\r
1360         \r
1361       ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_INVALID_GATEWAY), gShellNetwork1HiiHandle);\r
1362       ASSERT(ShellStatus == SHELL_INVALID_PARAMETER);\r
1363       goto ON_EXIT;\r
1364     }\r
1365 \r
1366     //\r
1367     // Set the configuration up, two route table entries are added:\r
1368     // one for the direct connected network, and another for the \r
1369     // default gateway. Remember, some structure members are cleared\r
1370     // by AllocateZeroPool\r
1371     //\r
1372     Config->Source = IP4_CONFIG_SOURCE_STATIC;\r
1373     Config->Ip4Info.RouteTableSize = 2;\r
1374 \r
1375     CopyMem (&Config->Ip4Info.StationAddress, &Ip.v4, sizeof (EFI_IPv4_ADDRESS));\r
1376     CopyMem (&Config->Ip4Info.SubnetMask, &Mask.v4, sizeof (EFI_IPv4_ADDRESS));\r
1377 \r
1378     Ip.Addr[0] = Ip.Addr[0] & Mask.Addr[0];\r
1379 \r
1380     CopyMem (&Config->Ip4Info.RouteTable[0].SubnetAddress, &Ip.v4, sizeof (EFI_IPv4_ADDRESS));\r
1381     CopyMem (&Config->Ip4Info.RouteTable[0].SubnetMask, &Mask.v4, sizeof (EFI_IPv4_ADDRESS));\r
1382     CopyMem (&Config->Ip4Info.RouteTable[1].GatewayAddress, &Gateway.v4, sizeof (EFI_IPv4_ADDRESS));\r
1383   } else {\r
1384     // neither static or DHCP.  error.\r
1385     ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_GEN_TOO_FEW), gShellNetwork1HiiHandle);\r
1386     ASSERT(ShellStatus == SHELL_INVALID_PARAMETER);\r
1387     goto ON_EXIT;\r
1388   }\r
1389 \r
1390   CopyMem (&Config->NicAddr, &Info->NicAddress, sizeof (NIC_ADDR));\r
1391   Config->Perment = Permanent;\r
1392 \r
1393   //\r
1394   // Use HII service to set NIC address\r
1395   //\r
1396   ShellStatus = IfconfigSetNicAddrByHii (Info, Config);\r
1397   if (ShellStatus != SHELL_SUCCESS) {\r
1398     ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_SET_FAIL), gShellNetwork1HiiHandle, ShellStatus^MAX_BIT);\r
1399     goto ON_EXIT;\r
1400   } \r
1401 \r
1402   Status = IfconfigStartIp4 (Info);\r
1403   if (EFI_ERROR(Status)) {\r
1404     ShellStatus = SHELL_ACCESS_DENIED;\r
1405   }\r
1406 \r
1407   if (ShellStatus != SHELL_SUCCESS) {\r
1408     ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_IP_CHILD_FAIL), gShellNetwork1HiiHandle, ShellStatus^MAX_BIT);\r
1409   }\r
1410   \r
1411 ON_EXIT:\r
1412   SHELL_FREE_NON_NULL(Config);\r
1413   \r
1414   return ShellStatus;\r
1415 }\r
1416 \r
1417 /**\r
1418   Show the address information for the nic specified.\r
1419 \r
1420   @param[in] Name   A pointer to the string containg the nic's name, if NULL, \r
1421                     all nics' information is shown.\r
1422 **/\r
1423 VOID\r
1424 EFIAPI\r
1425 IfconfigShowNicInfo (\r
1426   IN CONST CHAR16           *Name\r
1427   )\r
1428 {\r
1429   LIST_ENTRY                *Entry;\r
1430   LIST_ENTRY                *NextEntry;\r
1431   NIC_INFO                  *NicInfo;\r
1432   UINT32                    Index;\r
1433   EFI_IP4_IPCONFIG_DATA     *Ip4Config;\r
1434   EFI_IPv4_ADDRESS          Gateway;\r
1435   CONST CHAR16              *TempString;\r
1436 \r
1437   NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &NicInfoList) {\r
1438     NicInfo = BASE_CR (Entry, NIC_INFO, Link);\r
1439 \r
1440     TempString = (CHAR16*)NicInfo->Name;\r
1441     if ((Name != NULL) && (StringNoCaseCompare (&Name, &TempString) != 0)) {\r
1442       continue;\r
1443     }\r
1444 \r
1445     ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_NIC_NAME), gShellNetwork1HiiHandle, NicInfo->Name);\r
1446 \r
1447     ShellPrintHiiEx(\r
1448     -1,\r
1449     -1,\r
1450     NULL,\r
1451     STRING_TOKEN(STR_IFCONFIG_SHOW_MAC_ADDR), \r
1452     gShellNetwork1HiiHandle, \r
1453     (UINTN)NicInfo->NicAddress.MacAddr.Addr[0], \r
1454     (UINTN)NicInfo->NicAddress.MacAddr.Addr[1], \r
1455     (UINTN)NicInfo->NicAddress.MacAddr.Addr[2],\r
1456     (UINTN)NicInfo->NicAddress.MacAddr.Addr[3], \r
1457     (UINTN)NicInfo->NicAddress.MacAddr.Addr[4], \r
1458     (UINTN)NicInfo->NicAddress.MacAddr.Addr[5]\r
1459     );    \r
1460 \r
1461     Print (L"  Media State: %s\n", NicInfo->MediaPresent ? L"Media present" : L"Media disconnected");\r
1462 \r
1463     if (NicInfo->ConfigInfo == NULL) {\r
1464       ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_NIC_NOT_CONFIGURED), gShellNetwork1HiiHandle);\r
1465       continue;\r
1466     } \r
1467 \r
1468     if (NicInfo->ConfigInfo->Source == IP4_CONFIG_SOURCE_DHCP) {\r
1469       ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_CONFIG_SOURCE), gShellNetwork1HiiHandle, L"DHCP");\r
1470     } else if (NicInfo->ConfigInfo->Source == IP4_CONFIG_SOURCE_STATIC) {\r
1471       ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_CONFIG_SOURCE), gShellNetwork1HiiHandle, L"STATIC");\r
1472     } else {\r
1473       ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_CONFIG_SOURCE), gShellNetwork1HiiHandle, L"Unknown");\r
1474     }\r
1475 \r
1476     ShellPrintHiiEx(-1, -1, NULL,\r
1477       STRING_TOKEN (STR_IFCONFIG_PERMENT_STATUS),\r
1478       gShellNetwork1HiiHandle,\r
1479       (NicInfo->ConfigInfo->Perment? L"TRUE":L"FALSE")\r
1480       );\r
1481 \r
1482     Ip4Config = &NicInfo->ConfigInfo->Ip4Info;\r
1483 \r
1484     ShellPrintHiiEx(\r
1485       -1, \r
1486       -1, \r
1487       NULL,\r
1488       STRING_TOKEN (STR_IFCONFIG_SHOW_IP_ADDR), \r
1489       gShellNetwork1HiiHandle, \r
1490       L"IP address",\r
1491       (UINTN)Ip4Config->StationAddress.Addr[0],\r
1492       (UINTN)Ip4Config->StationAddress.Addr[1],\r
1493       (UINTN)Ip4Config->StationAddress.Addr[2],\r
1494       (UINTN)Ip4Config->StationAddress.Addr[3]\r
1495       );\r
1496     ShellPrintHiiEx(\r
1497       -1, \r
1498       -1, \r
1499       NULL,\r
1500       STRING_TOKEN (STR_IFCONFIG_SHOW_IP_ADDR), \r
1501       gShellNetwork1HiiHandle, \r
1502       L"Mask",\r
1503       (UINTN)Ip4Config->SubnetMask.Addr[0],\r
1504       (UINTN)Ip4Config->SubnetMask.Addr[1],\r
1505       (UINTN)Ip4Config->SubnetMask.Addr[2],\r
1506       (UINTN)Ip4Config->SubnetMask.Addr[3]\r
1507       );\r
1508 \r
1509     ZeroMem (&Gateway, sizeof (EFI_IPv4_ADDRESS));\r
1510     \r
1511     for (Index = 0; Index < Ip4Config->RouteTableSize; Index++) {\r
1512       if ((CompareMem (&Ip4Config->RouteTable[Index].SubnetAddress, &mZeroIp4Addr, sizeof (EFI_IPv4_ADDRESS)) == 0) &&\r
1513           (CompareMem (&Ip4Config->RouteTable[Index].SubnetMask   , &mZeroIp4Addr, sizeof (EFI_IPv4_ADDRESS)) == 0) ){\r
1514         CopyMem (&Gateway, &Ip4Config->RouteTable[Index].GatewayAddress, sizeof (EFI_IPv4_ADDRESS));\r
1515       }\r
1516     }\r
1517    \r
1518     ShellPrintHiiEx(\r
1519       -1, \r
1520       -1, \r
1521       NULL,\r
1522       STRING_TOKEN (STR_IFCONFIG_SHOW_IP_ADDR), \r
1523       gShellNetwork1HiiHandle, \r
1524       L"Gateway",\r
1525       (UINTN)Gateway.Addr[0],\r
1526       (UINTN)Gateway.Addr[1],\r
1527       (UINTN)Gateway.Addr[2],\r
1528       (UINTN)Gateway.Addr[3]\r
1529       );\r
1530 \r
1531     ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_ROUTES_SIZE), gShellNetwork1HiiHandle, Ip4Config->RouteTableSize);\r
1532 \r
1533     for (Index = 0; Index < Ip4Config->RouteTableSize; Index++) {\r
1534       ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_ROUTES_ENTRY_INDEX), gShellNetwork1HiiHandle, Index);\r
1535 \r
1536       ShellPrintHiiEx(\r
1537         -1, \r
1538         -1, \r
1539         NULL,\r
1540         STRING_TOKEN (STR_IFCONFIG_SHOW_IP_ADDR), \r
1541         gShellNetwork1HiiHandle, \r
1542         L"Subnet",\r
1543         (UINTN)Ip4Config->RouteTable[Index].SubnetAddress.Addr[0],\r
1544         (UINTN)Ip4Config->RouteTable[Index].SubnetAddress.Addr[1],\r
1545         (UINTN)Ip4Config->RouteTable[Index].SubnetAddress.Addr[2],\r
1546         (UINTN)Ip4Config->RouteTable[Index].SubnetAddress.Addr[3]\r
1547         );\r
1548 \r
1549       ShellPrintHiiEx(\r
1550         -1, \r
1551         -1, \r
1552         NULL,\r
1553         STRING_TOKEN (STR_IFCONFIG_SHOW_IP_ADDR), \r
1554         gShellNetwork1HiiHandle, \r
1555         L"Netmask",\r
1556         (UINTN)Ip4Config->RouteTable[Index].SubnetMask.Addr[0],\r
1557         (UINTN)Ip4Config->RouteTable[Index].SubnetMask.Addr[1],\r
1558         (UINTN)Ip4Config->RouteTable[Index].SubnetMask.Addr[2],\r
1559         (UINTN)Ip4Config->RouteTable[Index].SubnetMask.Addr[3]\r
1560         );\r
1561 \r
1562       ShellPrintHiiEx(\r
1563         -1, \r
1564         -1, \r
1565         NULL,\r
1566         STRING_TOKEN (STR_IFCONFIG_SHOW_IP_ADDR), \r
1567         gShellNetwork1HiiHandle, \r
1568         L"Gateway",\r
1569         (UINTN)Ip4Config->RouteTable[Index].GatewayAddress.Addr[0],\r
1570         (UINTN)Ip4Config->RouteTable[Index].GatewayAddress.Addr[1],\r
1571         (UINTN)Ip4Config->RouteTable[Index].GatewayAddress.Addr[2],\r
1572         (UINTN)Ip4Config->RouteTable[Index].GatewayAddress.Addr[3]\r
1573         );\r
1574     }\r
1575   }\r
1576 \r
1577   return ;\r
1578 }\r
1579 \r
1580 /**\r
1581   Clear address configuration for the nic specified.\r
1582 \r
1583   @param[in] Name     A pointer to the string containg the nic's name, \r
1584                       if NULL, all nics address configurations are cleared.\r
1585 \r
1586   @retval EFI_SUCCESS The address configuration is cleared.\r
1587   @return             Some error occurs.\r
1588 **/\r
1589 EFI_STATUS\r
1590 EFIAPI\r
1591 IfconfigClearNicAddr (\r
1592   IN CONST CHAR16                     *Name\r
1593   )\r
1594 {\r
1595   LIST_ENTRY                    *Entry;\r
1596   LIST_ENTRY                    *NextEntry;\r
1597   NIC_INFO                      *Info;\r
1598   EFI_STATUS                    Status;\r
1599   \r
1600   NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &NicInfoList) {\r
1601     Info = BASE_CR (Entry, NIC_INFO, Link);\r
1602 \r
1603     if ((Name != NULL) && (StrCmp (Name, Info->Name) != 0)) {\r
1604       continue;\r
1605     }\r
1606 \r
1607 //    if (Info->NicIp4Config == NULL) { \r
1608       Status = IfconfigSetNicAddrByHii (Info, NULL);\r
1609 //    } else {\r
1610 //      Status = Info->NicIp4Config->SetInfo (Info->NicIp4Config, NULL, TRUE);\r
1611 //    }\r
1612 \r
1613     if (EFI_ERROR (Status)) {\r
1614       return Status;\r
1615     }\r
1616   }\r
1617 \r
1618   return EFI_SUCCESS;\r
1619   \r
1620 }\r
1621 \r
1622 /**\r
1623   Function for 'ifconfig' command.\r
1624 \r
1625   @param[in] ImageHandle  Handle to the Image (NULL if Internal).\r
1626   @param[in] SystemTable  Pointer to the System Table (NULL if Internal).\r
1627 **/\r
1628 SHELL_STATUS\r
1629 EFIAPI\r
1630 ShellCommandRunIfconfig (\r
1631   IN EFI_HANDLE        ImageHandle,\r
1632   IN EFI_SYSTEM_TABLE  *SystemTable\r
1633   )\r
1634 {\r
1635   EFI_STATUS          Status;\r
1636   LIST_ENTRY          *Package;\r
1637   CHAR16              *ProblemParam;\r
1638   SHELL_STATUS        ShellStatus;\r
1639   BOOLEAN             ListOperation;\r
1640   BOOLEAN             ClearOperation;\r
1641   BOOLEAN             SetOperation;\r
1642   CONST CHAR16        *Item;\r
1643   LIST_ENTRY          *Entry;\r
1644   NIC_INFO            *Info;\r
1645 \r
1646   InitializeListHead (&NicInfoList);\r
1647   Status = EFI_INVALID_PARAMETER;\r
1648   ShellStatus = SHELL_SUCCESS;\r
1649 \r
1650   //\r
1651   // initialize the shell lib (we must be in non-auto-init...)\r
1652   //\r
1653   Status = ShellInitialize();\r
1654   ASSERT_EFI_ERROR(Status);\r
1655 \r
1656   //\r
1657   // parse the command line\r
1658   //\r
1659   Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);\r
1660   if (EFI_ERROR(Status)) {\r
1661     if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {\r
1662       ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellNetwork1HiiHandle, ProblemParam);\r
1663       FreePool(ProblemParam);\r
1664       ShellStatus = SHELL_INVALID_PARAMETER;\r
1665     } else {\r
1666       ASSERT(FALSE);\r
1667     }\r
1668 \r
1669     goto Done;\r
1670   }\r
1671 \r
1672   ClearOperation = ShellCommandLineGetFlag(Package, L"-c");\r
1673   ListOperation  = ShellCommandLineGetFlag(Package, L"-l");\r
1674   SetOperation   = ShellCommandLineGetFlag(Package, L"-s");\r
1675 \r
1676   if ((ClearOperation && ListOperation)\r
1677     ||(SetOperation   && ListOperation)\r
1678     ||(ClearOperation && SetOperation)\r
1679     ) {\r
1680     ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_CON), gShellNetwork1HiiHandle);\r
1681     ShellStatus = SHELL_INVALID_PARAMETER;\r
1682     goto Done;\r
1683   } else if (!ClearOperation && !ListOperation && !SetOperation) {\r
1684     ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellNetwork1HiiHandle);\r
1685     ShellStatus = SHELL_INVALID_PARAMETER;\r
1686     goto Done;\r
1687   }\r
1688     \r
1689     \r
1690   Status = IfconfigGetAllNicInfoByHii ();\r
1691   if (EFI_ERROR (Status)) {\r
1692     if (mIp4ConfigExist) {\r
1693       ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_GET_NIC_FAIL), gShellNetwork1HiiHandle, Status);\r
1694     } else {\r
1695       ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROTOCOL_NF), gShellNetwork1HiiHandle, L"gEfiIp4ConfigProtocolGuid", &gEfiIp4ConfigProtocolGuid);\r
1696     }\r
1697 \r
1698     return SHELL_NOT_FOUND;\r
1699   }\r
1700 \r
1701   if (ListOperation) {\r
1702     Item = ShellCommandLineGetValue (Package, L"-l");\r
1703 \r
1704     if (Item != NULL && CountSubItems(Item) > 1) {\r
1705       ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM_VAL), gShellNetwork1HiiHandle, L"-l");\r
1706       ShellStatus = SHELL_INVALID_PARAMETER;\r
1707       goto Done;\r
1708     } \r
1709     \r
1710     //\r
1711     // Show the configuration.\r
1712     //\r
1713     IfconfigShowNicInfo (Item);\r
1714   } else if (SetOperation) {\r
1715     Item = ShellCommandLineGetValue (Package, L"-s");\r
1716 \r
1717     //\r
1718     // The correct command line arguments for setting address are:\r
1719     // IfConfig -s eth0 DHCP [perment]\r
1720     // IfConfig -s eth0 static ip netmask gateway [perment]\r
1721     //\r
1722     if (Item == NULL || (CountSubItems(Item) < 2) || (CountSubItems(Item) > 6) || (CountSubItems(Item) == 4)) {\r
1723       ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_GEN_PROBLEM_VAL), gShellNetwork1HiiHandle, L"-s");\r
1724       ShellStatus = SHELL_INVALID_PARAMETER;\r
1725       goto Done;\r
1726     }\r
1727 \r
1728     ShellStatus = IfconfigSetNicAddr (CountSubItems(Item), Item);\r
1729   } else if (ClearOperation) {\r
1730     Item = ShellCommandLineGetValue (Package, L"-c");\r
1731 \r
1732     if (Item != NULL && CountSubItems(Item) > 1) {\r
1733       ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM_VAL), gShellNetwork1HiiHandle, L"-c");\r
1734       ShellStatus = SHELL_INVALID_PARAMETER;\r
1735       goto Done;\r
1736     }\r
1737 \r
1738     IfconfigClearNicAddr (Item);\r
1739   } else {\r
1740     ASSERT(FALSE);\r
1741   }\r
1742 \r
1743 Done:\r
1744   while (!IsListEmpty (&NicInfoList)) {\r
1745     Entry = NicInfoList.ForwardLink;\r
1746     Info  = BASE_CR (Entry, NIC_INFO, Link);\r
1747 \r
1748     RemoveEntryList (Entry);\r
1749 \r
1750     if (Info->ConfigInfo != NULL) {\r
1751       FreePool (Info->ConfigInfo);\r
1752     }\r
1753 \r
1754     FreePool (Info);\r
1755   }\r
1756 \r
1757   if (Package != NULL) {\r
1758     ShellCommandLineFreeVarList(Package);\r
1759   }\r
1760 \r
1761   return (ShellStatus);\r
1762 }\r