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