1 /** @file
2   The implementation for Shell command ifconfig based on IP4Config2 protocol.
3 
4   (C) Copyright 2013-2015 Hewlett-Packard Development Company, L.P.<BR>
5   Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>
6 
7   This program and the accompanying materials
8   are licensed and made available under the terms and conditions of the BSD License
9   which accompanies this distribution.  The full text of the license may be found at
10   http://opensource.org/licenses/bsd-license.php.
11 
12   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
14 
15 **/
16 
17 #include "UefiShellNetwork1CommandsLib.h"
18 
19 typedef enum {
20   IfConfigOpList     = 1,
21   IfConfigOpSet      = 2,
22   IfConfigOpClear    = 3
23 } IFCONFIG_OPCODE;
24 
25 typedef enum {
26   VarCheckReserved      = -1,
27   VarCheckOk            = 0,
28   VarCheckDuplicate,
29   VarCheckConflict,
30   VarCheckUnknown,
31   VarCheckLackValue,
32   VarCheckOutOfMem
33 } VAR_CHECK_CODE;
34 
35 typedef enum {
36   FlagTypeSingle         = 0,
37   FlagTypeNeedVar,
38   FlagTypeNeedSet,
39   FlagTypeSkipUnknown
40 } VAR_CHECK_FLAG_TYPE;
41 
42 #define MACADDRMAXSIZE    32
43 
44 typedef struct _IFCONFIG_INTERFACE_CB {
45   EFI_HANDLE                                  NicHandle;
46   LIST_ENTRY                                  Link;
47   EFI_IP4_CONFIG2_PROTOCOL                    *IfCfg;
48   EFI_IP4_CONFIG2_INTERFACE_INFO              *IfInfo;
49   EFI_IP4_CONFIG2_POLICY                      Policy;
50   UINT32                                      DnsCnt;
51   EFI_IPv4_ADDRESS                            DnsAddr[1];
52 } IFCONFIG_INTERFACE_CB;
53 
54 typedef struct _ARG_LIST ARG_LIST;
55 
56 struct _ARG_LIST {
57   ARG_LIST    *Next;
58   CHAR16      *Arg;
59 };
60 
61 typedef struct _IFCONFIG4_PRIVATE_DATA {
62   LIST_ENTRY  IfList;
63 
64   UINT32      OpCode;
65   CHAR16      *IfName;
66   ARG_LIST    *VarArg;
67 } IFCONFIG_PRIVATE_DATA;
68 
69 typedef struct _VAR_CHECK_ITEM{
70   CHAR16                 *FlagStr;
71   UINT32                 FlagID;
72   UINT32                 ConflictMask;
73   VAR_CHECK_FLAG_TYPE    FlagType;
74 } VAR_CHECK_ITEM;
75 
76 SHELL_PARAM_ITEM    mIfConfigCheckList[] = {
77   {
78     L"-b",
79     TypeFlag
80   },
81   {
82     L"-l",
83     TypeValue
84   },
85   {
86     L"-r",
87     TypeValue
88   },
89   {
90     L"-c",
91     TypeValue
92   },
93   {
94     L"-s",
95     TypeMaxValue
96   },
97   {
98     NULL,
99     TypeMax
100   },
101 };
102 
103 VAR_CHECK_ITEM  mSetCheckList[] = {
104   {
105    L"static",
106     0x00000001,
107     0x00000001,
108     FlagTypeSingle
109   },
110   {
111     L"dhcp",
112     0x00000002,
113     0x00000001,
114     FlagTypeSingle
115   },
116   {
117     L"dns",
118     0x00000008,
119     0x00000004,
120     FlagTypeSingle
121   },
122   {
123     NULL,
124     0x0,
125     0x0,
126     FlagTypeSkipUnknown
127   },
128 };
129 
130 STATIC CONST CHAR16 PermanentString[10] = L"PERMANENT";
131 
132 /**
133   Split a string with specified separator and save the substring to a list.
134 
135   @param[in]    String       The pointer of the input string.
136   @param[in]    Separator    The specified separator.
137 
138   @return The pointer of headnode of ARG_LIST.
139 
140 **/
141 ARG_LIST *
SplitStrToList(IN CONST CHAR16 * String,IN CHAR16 Separator)142 SplitStrToList (
143   IN CONST CHAR16    *String,
144   IN CHAR16          Separator
145   )
146 {
147   CHAR16      *Str;
148   CHAR16      *ArgStr;
149   ARG_LIST    *ArgList;
150   ARG_LIST    *ArgNode;
151 
152   if (*String == L'\0') {
153     return NULL;
154   }
155 
156   //
157   // Copy the CONST string to a local copy.
158   //
159   Str = AllocateCopyPool (StrSize (String), String);
160   ASSERT (Str != NULL);
161   ArgStr  = Str;
162 
163   //
164   // init a node for the list head.
165   //
166   ArgNode = (ARG_LIST *) AllocateZeroPool (sizeof (ARG_LIST));
167   ASSERT (ArgNode != NULL);
168   ArgList = ArgNode;
169 
170   //
171   // Split the local copy and save in the list node.
172   //
173   while (*Str != L'\0') {
174     if (*Str == Separator) {
175       *Str          = L'\0';
176       ArgNode->Arg  = ArgStr;
177       ArgStr        = Str + 1;
178       ArgNode->Next = (ARG_LIST *) AllocateZeroPool (sizeof (ARG_LIST));
179       ASSERT (ArgNode->Next != NULL);
180       ArgNode = ArgNode->Next;
181     }
182 
183     Str++;
184   }
185 
186   ArgNode->Arg  = ArgStr;
187   ArgNode->Next = NULL;
188 
189   return ArgList;
190 }
191 
192 /**
193   Check the correctness of input Args with '-s' option.
194 
195   @param[in]    CheckList    The pointer of VAR_CHECK_ITEM array.
196   @param[in]    Name         The pointer of input arg.
197   @param[in]    Init         The switch to execute the check.
198 
199   @return   VarCheckOk          Valid parameter or Initialize check successfully.
200   @return   VarCheckDuplicate   Duplicated parameter happened.
201   @return   VarCheckConflict    Conflicted parameter happened
202   @return   VarCheckUnknown     Unknown parameter.
203 
204 **/
205 VAR_CHECK_CODE
IfConfigRetriveCheckListByName(IN VAR_CHECK_ITEM * CheckList,IN CHAR16 * Name,IN BOOLEAN Init)206 IfConfigRetriveCheckListByName(
207   IN VAR_CHECK_ITEM    *CheckList,
208   IN CHAR16            *Name,
209   IN BOOLEAN           Init
210 )
211 {
212   STATIC UINT32     CheckDuplicate;
213   STATIC UINT32     CheckConflict;
214   VAR_CHECK_CODE    RtCode;
215   UINT32            Index;
216   VAR_CHECK_ITEM    Arg;
217 
218   if (Init) {
219     CheckDuplicate = 0;
220     CheckConflict  = 0;
221     return VarCheckOk;
222   }
223 
224   RtCode  = VarCheckOk;
225   Index   = 0;
226   Arg     = CheckList[Index];
227 
228   //
229   // Check the Duplicated/Conflicted/Unknown input Args.
230   //
231   while (Arg.FlagStr != NULL) {
232     if (StrCmp (Arg.FlagStr, Name) == 0) {
233 
234       if (CheckDuplicate & Arg.FlagID) {
235         RtCode = VarCheckDuplicate;
236         break;
237       }
238 
239       if (CheckConflict & Arg.ConflictMask) {
240         RtCode = VarCheckConflict;
241         break;
242       }
243 
244       CheckDuplicate |= Arg.FlagID;
245       CheckConflict  |= Arg.ConflictMask;
246       break;
247     }
248 
249     Arg = CheckList[++Index];
250   }
251 
252   if (Arg.FlagStr == NULL) {
253     RtCode = VarCheckUnknown;
254   }
255 
256   return RtCode;
257 }
258 
259 /**
260   The notify function of create event when performing a manual config.
261 
262   @param[in]    Event        The event this notify function registered to.
263   @param[in]    Context      Pointer to the context data registered to the event.
264 
265 **/
266 VOID
267 EFIAPI
IfConfigManualAddressNotify(IN EFI_EVENT Event,IN VOID * Context)268 IfConfigManualAddressNotify (
269   IN EFI_EVENT    Event,
270   IN VOID         *Context
271   )
272 {
273   *((BOOLEAN *) Context) = TRUE;
274 }
275 
276 
277 /**
278   Create an IP child, use it to start the auto configuration, then destroy it.
279 
280   @param[in] Controller       The controller which has the service installed.
281   @param[in] Image            The image handle used to open service.
282 
283   @retval EFI_SUCCESS         The configuration is done.
284 **/
285 EFI_STATUS
286 EFIAPI
IfConfigStartIp4(IN EFI_HANDLE Controller,IN EFI_HANDLE Image)287 IfConfigStartIp4(
288   IN  EFI_HANDLE            Controller,
289   IN  EFI_HANDLE            Image
290   )
291 {
292   EFI_IP4_PROTOCOL              *Ip4;
293   EFI_HANDLE                    Ip4Handle;
294   EFI_IP4_CONFIG_DATA           Ip4ConfigData;
295   EFI_STATUS                    Status;
296 
297   //
298   // Get the Ip4ServiceBinding Protocol
299   //
300   Ip4Handle     = NULL;
301   Ip4           = NULL;
302 
303   Status = NetLibCreateServiceChild (
304              Controller,
305              Image,
306              &gEfiIp4ServiceBindingProtocolGuid,
307              &Ip4Handle
308              );
309 
310   if (EFI_ERROR (Status)) {
311     return Status;
312   }
313 
314   Status = gBS->OpenProtocol (
315                  Ip4Handle,
316                  &gEfiIp4ProtocolGuid,
317                  (VOID **) &Ip4,
318                  Controller,
319                  Image,
320                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
321                  );
322 
323   if (EFI_ERROR (Status)) {
324     goto ON_EXIT;
325   }
326 
327   Ip4ConfigData.DefaultProtocol          = EFI_IP_PROTO_ICMP;
328   Ip4ConfigData.AcceptAnyProtocol        = FALSE;
329   Ip4ConfigData.AcceptIcmpErrors         = FALSE;
330   Ip4ConfigData.AcceptBroadcast          = FALSE;
331   Ip4ConfigData.AcceptPromiscuous        = FALSE;
332   Ip4ConfigData.UseDefaultAddress        = TRUE;
333   ZeroMem (&Ip4ConfigData.StationAddress, sizeof (EFI_IPv4_ADDRESS));
334   ZeroMem (&Ip4ConfigData.SubnetMask, sizeof (EFI_IPv4_ADDRESS));
335   Ip4ConfigData.TypeOfService            = 0;
336   Ip4ConfigData.TimeToLive               = 1;
337   Ip4ConfigData.DoNotFragment            = FALSE;
338   Ip4ConfigData.RawData                  = FALSE;
339   Ip4ConfigData.ReceiveTimeout           = 0;
340   Ip4ConfigData.TransmitTimeout          = 0;
341 
342   Ip4->Configure (Ip4, &Ip4ConfigData);
343 
344 ON_EXIT:
345   NetLibDestroyServiceChild (
346     Controller,
347     Image,
348     &gEfiIp4ServiceBindingProtocolGuid,
349     Ip4Handle
350     );
351 
352   return Status;
353 }
354 
355 
356 /**
357   Print MAC address.
358 
359   @param[in]    Node    The pointer of MAC address buffer.
360   @param[in]    Size    The size of MAC address buffer.
361 
362 **/
363 VOID
IfConfigPrintMacAddr(IN UINT8 * Node,IN UINT32 Size)364 IfConfigPrintMacAddr (
365   IN UINT8     *Node,
366   IN UINT32    Size
367   )
368 {
369   UINTN    Index;
370 
371   ASSERT (Size <= MACADDRMAXSIZE);
372 
373   for (Index = 0; Index < Size; Index++) {
374     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_MAC_ADDR_BODY), gShellNetwork1HiiHandle, Node[Index]);
375     if (Index + 1 < Size) {
376       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_COLON), gShellNetwork1HiiHandle);
377     }
378   }
379 
380   ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_NEWLINE), gShellNetwork1HiiHandle);
381 }
382 
383 
384 /**
385   The get current status of all handles.
386 
387   @param[in]   IfName         The pointer of IfName(interface name).
388   @param[in]   IfList         The pointer of IfList(interface list).
389 
390   @retval EFI_SUCCESS    The get status processed successfully.
391   @retval others         The get status process failed.
392 
393 **/
394 EFI_STATUS
IfConfigGetInterfaceInfo(IN CHAR16 * IfName,IN LIST_ENTRY * IfList)395 IfConfigGetInterfaceInfo (
396   IN CHAR16        *IfName,
397   IN LIST_ENTRY    *IfList
398   )
399 {
400   EFI_STATUS                       Status;
401   UINTN                            HandleIndex;
402   UINTN                            HandleNum;
403   EFI_HANDLE                       *HandleBuffer;
404   EFI_IP4_CONFIG2_PROTOCOL         *Ip4Cfg2;
405   EFI_IP4_CONFIG2_INTERFACE_INFO   *IfInfo;
406   IFCONFIG_INTERFACE_CB            *IfCb;
407   UINTN                            DataSize;
408 
409   HandleBuffer = NULL;
410   HandleNum    = 0;
411 
412   IfInfo       = NULL;
413   IfCb         = NULL;
414 
415   //
416   // Locate all the handles with ip4 service binding protocol.
417   //
418   Status = gBS->LocateHandleBuffer (
419                   ByProtocol,
420                   &gEfiIp4ServiceBindingProtocolGuid,
421                   NULL,
422                   &HandleNum,
423                   &HandleBuffer
424                  );
425   if (EFI_ERROR (Status) || (HandleNum == 0)) {
426     return Status;
427   }
428 
429   //
430   // Enumerate all handles that installed with ip4 service binding protocol.
431   //
432   for (HandleIndex = 0; HandleIndex < HandleNum; HandleIndex++) {
433     IfCb      = NULL;
434     IfInfo    = NULL;
435     DataSize  = 0;
436 
437     //
438     // Ip4config protocol and ip4 service binding protocol are installed
439     // on the same handle.
440     //
441     ASSERT (HandleBuffer != NULL);
442     Status = gBS->HandleProtocol (
443                     HandleBuffer[HandleIndex],
444                     &gEfiIp4Config2ProtocolGuid,
445                     (VOID **) &Ip4Cfg2
446                     );
447 
448     if (EFI_ERROR (Status)) {
449       goto ON_ERROR;
450     }
451 
452     //
453     // Get the interface information size.
454     //
455     Status = Ip4Cfg2->GetData (
456                        Ip4Cfg2,
457                        Ip4Config2DataTypeInterfaceInfo,
458                        &DataSize,
459                        NULL
460                        );
461 
462     if (Status != EFI_BUFFER_TOO_SMALL) {
463       goto ON_ERROR;
464     }
465 
466     IfInfo = AllocateZeroPool (DataSize);
467 
468     if (IfInfo == NULL) {
469       Status = EFI_OUT_OF_RESOURCES;
470       goto ON_ERROR;
471     }
472 
473     //
474     // Get the interface info.
475     //
476     Status = Ip4Cfg2->GetData (
477                        Ip4Cfg2,
478                        Ip4Config2DataTypeInterfaceInfo,
479                        &DataSize,
480                        IfInfo
481                        );
482 
483     if (EFI_ERROR (Status)) {
484       goto ON_ERROR;
485     }
486 
487     //
488     // Check the interface name if required.
489     //
490     if ((IfName != NULL) && (StrCmp (IfName, IfInfo->Name) != 0)) {
491       FreePool (IfInfo);
492       continue;
493     }
494 
495     DataSize = 0;
496 
497     //
498     // Get the size of dns server list.
499     //
500     Status = Ip4Cfg2->GetData (
501                        Ip4Cfg2,
502                        Ip4Config2DataTypeDnsServer,
503                        &DataSize,
504                        NULL
505                        );
506 
507     if ((Status != EFI_BUFFER_TOO_SMALL) && (Status != EFI_NOT_FOUND)) {
508       goto ON_ERROR;
509     }
510 
511     IfCb = AllocateZeroPool (sizeof (IFCONFIG_INTERFACE_CB) + DataSize);
512 
513     if (IfCb == NULL) {
514       Status = EFI_OUT_OF_RESOURCES;
515       goto ON_ERROR;
516     }
517 
518     IfCb->NicHandle = HandleBuffer[HandleIndex];
519     IfCb->IfInfo    = IfInfo;
520     IfCb->IfCfg     = Ip4Cfg2;
521     IfCb->DnsCnt    = (UINT32) (DataSize / sizeof (EFI_IPv4_ADDRESS));
522 
523     //
524     // Get the dns server list if has.
525     //
526     if (DataSize > 0) {
527       Status = Ip4Cfg2->GetData (
528                          Ip4Cfg2,
529                          Ip4Config2DataTypeDnsServer,
530                          &DataSize,
531                          IfCb->DnsAddr
532                          );
533 
534       if (EFI_ERROR (Status)) {
535         goto ON_ERROR;
536       }
537     }
538 
539     //
540     // Get the config policy.
541     //
542     DataSize = sizeof (EFI_IP4_CONFIG2_POLICY);
543     Status   = Ip4Cfg2->GetData (
544                          Ip4Cfg2,
545                          Ip4Config2DataTypePolicy,
546                          &DataSize,
547                          &IfCb->Policy
548                          );
549 
550     if (EFI_ERROR (Status)) {
551       goto ON_ERROR;
552     }
553 
554     InsertTailList (IfList, &IfCb->Link);
555 
556     if ((IfName != NULL) && (StrCmp (IfName, IfInfo->Name) == 0)) {
557       //
558       // Only need the appointed interface, keep the allocated buffer.
559       //
560       IfCb   = NULL;
561       IfInfo = NULL;
562       break;
563     }
564   }
565 
566   if (HandleBuffer != NULL) {
567     FreePool (HandleBuffer);
568   }
569 
570   return EFI_SUCCESS;
571 
572 ON_ERROR:
573 
574   if (IfInfo != NULL) {
575     FreePool (IfInfo);
576   }
577 
578   if (IfCb != NULL) {
579     FreePool (IfCb);
580   }
581 
582   return Status;
583 }
584 
585 /**
586   The list process of the ifconfig command.
587 
588   @param[in]   IfList    The pointer of IfList(interface list).
589 
590   @retval SHELL_SUCCESS  The ifconfig command list processed successfully.
591   @retval others         The ifconfig command list process failed.
592 
593 **/
594 SHELL_STATUS
IfConfigShowInterfaceInfo(IN LIST_ENTRY * IfList)595 IfConfigShowInterfaceInfo (
596   IN LIST_ENTRY    *IfList
597   )
598 {
599   LIST_ENTRY                   *Entry;
600   LIST_ENTRY                   *Next;
601   IFCONFIG_INTERFACE_CB        *IfCb;
602   BOOLEAN                       MediaPresent;
603   EFI_IPv4_ADDRESS              Gateway;
604   UINT32                        Index;
605 
606   MediaPresent = TRUE;
607 
608   if (IsListEmpty (IfList)) {
609     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INVALID_INTERFACE), gShellNetwork1HiiHandle);
610   }
611 
612   //
613   // Go through the interface list.
614   //
615   NET_LIST_FOR_EACH_SAFE (Entry, Next, IfList) {
616     IfCb = NET_LIST_USER_STRUCT (Entry, IFCONFIG_INTERFACE_CB, Link);
617 
618     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_BREAK), gShellNetwork1HiiHandle);
619 
620     //
621     // Print interface name.
622     //
623     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_IF_NAME), gShellNetwork1HiiHandle, IfCb->IfInfo->Name);
624 
625     //
626     // Get Media State.
627     //
628     NetLibDetectMedia (IfCb->NicHandle, &MediaPresent);
629     if (!MediaPresent) {
630       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_MEDIA_STATE), gShellNetwork1HiiHandle, L"Media disconnected");
631     } else {
632       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_MEDIA_STATE), gShellNetwork1HiiHandle, L"Media present");
633     }
634 
635     //
636     // Print interface config policy.
637     //
638     if (IfCb->Policy == Ip4Config2PolicyDhcp) {
639       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_POLICY_DHCP), gShellNetwork1HiiHandle);
640     } else {
641       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_POLICY_MAN), gShellNetwork1HiiHandle);
642     }
643 
644     //
645     // Print mac address of the interface.
646     //
647     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_MAC_ADDR_HEAD), gShellNetwork1HiiHandle);
648 
649     IfConfigPrintMacAddr (
650       IfCb->IfInfo->HwAddress.Addr,
651       IfCb->IfInfo->HwAddressSize
652       );
653 
654     //
655     // Print IPv4 address list of the interface.
656     //
657     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_IP_ADDR_HEAD), gShellNetwork1HiiHandle);
658 
659     ShellPrintHiiEx(
660       -1,
661       -1,
662       NULL,
663       STRING_TOKEN (STR_IFCONFIG_INFO_IP_ADDR_BODY),
664       gShellNetwork1HiiHandle,
665       (UINTN)IfCb->IfInfo->StationAddress.Addr[0],
666       (UINTN)IfCb->IfInfo->StationAddress.Addr[1],
667       (UINTN)IfCb->IfInfo->StationAddress.Addr[2],
668       (UINTN)IfCb->IfInfo->StationAddress.Addr[3]
669       );
670 
671     //
672     // Print subnet mask list of the interface.
673     //
674     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_SUBNET_MASK_HEAD), gShellNetwork1HiiHandle);
675 
676     ShellPrintHiiEx(
677       -1,
678       -1,
679       NULL,
680       STRING_TOKEN (STR_IFCONFIG_INFO_IP_ADDR_BODY),
681       gShellNetwork1HiiHandle,
682       (UINTN)IfCb->IfInfo->SubnetMask.Addr[0],
683       (UINTN)IfCb->IfInfo->SubnetMask.Addr[1],
684       (UINTN)IfCb->IfInfo->SubnetMask.Addr[2],
685       (UINTN)IfCb->IfInfo->SubnetMask.Addr[3]
686       );
687 
688     //
689     // Print default gateway of the interface.
690     //
691     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_GATEWAY_HEAD), gShellNetwork1HiiHandle);
692 
693     ZeroMem (&Gateway, sizeof (EFI_IPv4_ADDRESS));
694 
695     for (Index = 0; Index < IfCb->IfInfo->RouteTableSize; Index++) {
696       if ((CompareMem (&IfCb->IfInfo->RouteTable[Index].SubnetAddress, &mZeroIp4Addr, sizeof (EFI_IPv4_ADDRESS)) == 0) &&
697           (CompareMem (&IfCb->IfInfo->RouteTable[Index].SubnetMask   , &mZeroIp4Addr, sizeof (EFI_IPv4_ADDRESS)) == 0) ){
698         CopyMem (&Gateway, &IfCb->IfInfo->RouteTable[Index].GatewayAddress, sizeof (EFI_IPv4_ADDRESS));
699       }
700     }
701 
702     ShellPrintHiiEx(
703       -1,
704       -1,
705       NULL,
706       STRING_TOKEN (STR_IFCONFIG_INFO_IP_ADDR_BODY),
707       gShellNetwork1HiiHandle,
708       (UINTN)Gateway.Addr[0],
709       (UINTN)Gateway.Addr[1],
710       (UINTN)Gateway.Addr[2],
711       (UINTN)Gateway.Addr[3]
712       );
713 
714     //
715     // Print route table entry.
716     //
717     ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_ROUTES_SIZE), gShellNetwork1HiiHandle, IfCb->IfInfo->RouteTableSize);
718 
719     for (Index = 0; Index < IfCb->IfInfo->RouteTableSize; Index++) {
720       ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_ROUTES_ENTRY_INDEX), gShellNetwork1HiiHandle, Index);
721 
722       ShellPrintHiiEx(
723         -1,
724         -1,
725         NULL,
726         STRING_TOKEN (STR_IFCONFIG_SHOW_IP_ADDR),
727         gShellNetwork1HiiHandle,
728         L"Subnet ",
729         (UINTN)IfCb->IfInfo->RouteTable[Index].SubnetAddress.Addr[0],
730         (UINTN)IfCb->IfInfo->RouteTable[Index].SubnetAddress.Addr[1],
731         (UINTN)IfCb->IfInfo->RouteTable[Index].SubnetAddress.Addr[2],
732         (UINTN)IfCb->IfInfo->RouteTable[Index].SubnetAddress.Addr[3]
733         );
734 
735       ShellPrintHiiEx(
736         -1,
737         -1,
738         NULL,
739         STRING_TOKEN (STR_IFCONFIG_SHOW_IP_ADDR),
740         gShellNetwork1HiiHandle,
741         L"Netmask",
742         (UINTN)IfCb->IfInfo->RouteTable[Index].SubnetMask.Addr[0],
743         (UINTN)IfCb->IfInfo->RouteTable[Index].SubnetMask.Addr[1],
744         (UINTN)IfCb->IfInfo->RouteTable[Index].SubnetMask.Addr[2],
745         (UINTN)IfCb->IfInfo->RouteTable[Index].SubnetMask.Addr[3]
746         );
747 
748       ShellPrintHiiEx(
749         -1,
750         -1,
751         NULL,
752         STRING_TOKEN (STR_IFCONFIG_SHOW_IP_ADDR),
753         gShellNetwork1HiiHandle,
754         L"Gateway",
755         (UINTN)IfCb->IfInfo->RouteTable[Index].GatewayAddress.Addr[0],
756         (UINTN)IfCb->IfInfo->RouteTable[Index].GatewayAddress.Addr[1],
757         (UINTN)IfCb->IfInfo->RouteTable[Index].GatewayAddress.Addr[2],
758         (UINTN)IfCb->IfInfo->RouteTable[Index].GatewayAddress.Addr[3]
759         );
760     }
761 
762     //
763     // Print dns server addresses list of the interface if has.
764     //
765     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_DNS_ADDR_HEAD), gShellNetwork1HiiHandle);
766 
767     for (Index = 0; Index < IfCb->DnsCnt; Index++) {
768       ShellPrintHiiEx(
769         -1,
770         -1,
771         NULL,
772         STRING_TOKEN (STR_IFCONFIG_INFO_DNS_ADDR_BODY),
773         gShellNetwork1HiiHandle,
774         (UINTN) IfCb->DnsAddr[Index].Addr[0],
775         (UINTN) IfCb->DnsAddr[Index].Addr[1],
776         (UINTN) IfCb->DnsAddr[Index].Addr[2],
777         (UINTN) IfCb->DnsAddr[Index].Addr[3]
778         );
779 
780       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_NEWLINE), gShellNetwork1HiiHandle);
781     }
782   }
783 
784   ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_BREAK), gShellNetwork1HiiHandle);
785 
786   return SHELL_SUCCESS;
787 }
788 
789 /**
790   The clean process of the ifconfig command to clear interface info.
791 
792   @param[in]   IfList    The pointer of IfList(interface list).
793 
794   @retval SHELL_SUCCESS  The ifconfig command clean processed successfully.
795   @retval others         The ifconfig command clean process failed.
796 
797 **/
798 SHELL_STATUS
IfConfigClearInterfaceInfo(IN LIST_ENTRY * IfList)799 IfConfigClearInterfaceInfo (
800   IN LIST_ENTRY    *IfList
801   )
802 {
803   EFI_STATUS                Status;
804   SHELL_STATUS              ShellStatus;
805   LIST_ENTRY                *Entry;
806   LIST_ENTRY                *Next;
807   IFCONFIG_INTERFACE_CB     *IfCb;
808   EFI_IP4_CONFIG2_POLICY    Policy;
809 
810   Policy = Ip4Config2PolicyDhcp;
811   Status = EFI_SUCCESS;
812   ShellStatus = SHELL_SUCCESS;
813 
814   if (IsListEmpty (IfList)) {
815     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INVALID_INTERFACE), gShellNetwork1HiiHandle);
816   }
817 
818   //
819   // Go through the interface list.
820   //
821   NET_LIST_FOR_EACH_SAFE (Entry, Next, IfList) {
822     IfCb = NET_LIST_USER_STRUCT (Entry, IFCONFIG_INTERFACE_CB, Link);
823 
824     Status = IfCb->IfCfg->SetData (
825                             IfCb->IfCfg,
826                             Ip4Config2DataTypePolicy,
827                             sizeof (EFI_IP4_CONFIG2_POLICY),
828                             &Policy
829                             );
830     if (EFI_ERROR (Status)) {
831       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_AD), gShellNetwork1HiiHandle, L"ifconfig");
832       ShellStatus = SHELL_ACCESS_DENIED;
833       break;
834     }
835   }
836 
837   return ShellStatus;
838 }
839 
840 /**
841   The set process of the ifconfig command.
842 
843   @param[in]   IfList    The pointer of IfList(interface list).
844   @param[in]   VarArg    The pointer of ARG_LIST(Args with "-s" option).
845 
846   @retval SHELL_SUCCESS  The ifconfig command set processed successfully.
847   @retval others         The ifconfig command set process failed.
848 
849 **/
850 SHELL_STATUS
IfConfigSetInterfaceInfo(IN LIST_ENTRY * IfList,IN ARG_LIST * VarArg)851 IfConfigSetInterfaceInfo (
852   IN LIST_ENTRY    *IfList,
853   IN ARG_LIST      *VarArg
854   )
855 {
856   EFI_STATUS                       Status;
857   SHELL_STATUS                     ShellStatus;
858   IFCONFIG_INTERFACE_CB            *IfCb;
859   VAR_CHECK_CODE                   CheckCode;
860   EFI_EVENT                        TimeOutEvt;
861   EFI_EVENT                        MappedEvt;
862   BOOLEAN                          IsAddressOk;
863 
864   EFI_IP4_CONFIG2_POLICY           Policy;
865   EFI_IP4_CONFIG2_MANUAL_ADDRESS   ManualAddress;
866   UINTN                            DataSize;
867   EFI_IPv4_ADDRESS                 Gateway;
868   EFI_IPv4_ADDRESS                 *Dns;
869   ARG_LIST                         *Tmp;
870   UINTN                            Index;
871 
872   CONST CHAR16* TempString;
873 
874   Dns = NULL;
875 
876   if (IsListEmpty (IfList)) {
877     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INVALID_INTERFACE), gShellNetwork1HiiHandle);
878     return SHELL_INVALID_PARAMETER;
879   }
880 
881   //
882   // Make sure to set only one interface each time.
883   //
884   IfCb   = NET_LIST_USER_STRUCT (IfList->ForwardLink, IFCONFIG_INTERFACE_CB, Link);
885   Status = EFI_SUCCESS;
886   ShellStatus = SHELL_SUCCESS;
887 
888   //
889   // Initialize check list mechanism.
890   //
891   CheckCode = IfConfigRetriveCheckListByName(
892                 NULL,
893                 NULL,
894                 TRUE
895                 );
896 
897   //
898   // Create events & timers for asynchronous settings.
899   //
900   Status = gBS->CreateEvent (
901                   EVT_TIMER,
902                   TPL_CALLBACK,
903                   NULL,
904                   NULL,
905                   &TimeOutEvt
906                   );
907   if (EFI_ERROR (Status)) {
908     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_AD), gShellNetwork1HiiHandle, L"ifconfig");
909     ShellStatus = SHELL_ACCESS_DENIED;
910     goto ON_EXIT;
911   }
912 
913   Status = gBS->CreateEvent (
914                   EVT_NOTIFY_SIGNAL,
915                   TPL_NOTIFY,
916                   IfConfigManualAddressNotify,
917                   &IsAddressOk,
918                   &MappedEvt
919                   );
920   if (EFI_ERROR (Status)) {
921     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_AD), gShellNetwork1HiiHandle, L"ifconfig");
922     ShellStatus = SHELL_ACCESS_DENIED;
923     goto ON_EXIT;
924   }
925 
926   //
927   // Parse the setting variables.
928   //
929   while (VarArg != NULL) {
930     //
931     // Check invalid parameters (duplication & unknown & conflict).
932     //
933     CheckCode = IfConfigRetriveCheckListByName(
934                   mSetCheckList,
935                   VarArg->Arg,
936                   FALSE
937                   );
938 
939     if (VarCheckOk != CheckCode) {
940       switch (CheckCode) {
941         case VarCheckDuplicate:
942           ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_DUPLICATE_COMMAND), gShellNetwork1HiiHandle, VarArg->Arg);
943           break;
944 
945         case VarCheckConflict:
946           ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_CONFLICT_COMMAND), gShellNetwork1HiiHandle, VarArg->Arg);
947           break;
948 
949         case VarCheckUnknown:
950           //
951           // To handle unsupported option.
952           //
953           TempString = PermanentString;
954           if (StringNoCaseCompare(&VarArg->Arg, &TempString) == 0) {
955             ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_UNSUPPORTED_OPTION), gShellNetwork1HiiHandle, PermanentString);
956             goto ON_EXIT;
957           }
958 
959           //
960           // To handle unknown option.
961           //
962           ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_UNKNOWN_COMMAND), gShellNetwork1HiiHandle, VarArg->Arg);
963           break;
964 
965         default:
966           break;
967       }
968 
969       VarArg = VarArg->Next;
970       continue;
971     }
972 
973     //
974     // Process valid variables.
975     //
976     if (StrCmp(VarArg->Arg, L"dhcp") == 0) {
977       if (IfCb->Policy == Ip4Config2PolicyDhcp) {
978         Status = IfConfigStartIp4 (IfCb->NicHandle, gImageHandle);
979         if (EFI_ERROR(Status)) {
980           ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_AD), gShellNetwork1HiiHandle, L"ifconfig");
981           ShellStatus = SHELL_ACCESS_DENIED;
982           goto ON_EXIT;
983         }
984       } else {
985         //
986         // Set dhcp config policy
987         //
988         Policy = Ip4Config2PolicyDhcp;
989         Status = IfCb->IfCfg->SetData (
990                                 IfCb->IfCfg,
991                                 Ip4Config2DataTypePolicy,
992                                 sizeof (EFI_IP4_CONFIG2_POLICY),
993                                 &Policy
994                                 );
995         if (EFI_ERROR(Status)) {
996           ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_AD), gShellNetwork1HiiHandle, L"ifconfig");
997           ShellStatus = SHELL_ACCESS_DENIED;
998           goto ON_EXIT;
999         }
1000       }
1001 
1002       VarArg= VarArg->Next;
1003 
1004     } else if (StrCmp (VarArg->Arg, L"static") == 0) {
1005       VarArg= VarArg->Next;
1006       if (VarArg == NULL) {
1007         ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_LACK_COMMAND), gShellNetwork1HiiHandle);
1008         ShellStatus = SHELL_INVALID_PARAMETER;
1009         goto ON_EXIT;
1010       }
1011 
1012       ZeroMem (&ManualAddress, sizeof (ManualAddress));
1013 
1014       //
1015       // Get manual IP address.
1016       //
1017       Status = NetLibStrToIp4 (VarArg->Arg, &ManualAddress.Address);
1018       if (EFI_ERROR(Status)) {
1019         ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_INVALID_IPADDRESS), gShellNetwork1HiiHandle, VarArg->Arg);
1020         ShellStatus = SHELL_INVALID_PARAMETER;
1021         goto ON_EXIT;
1022       }
1023 
1024       //
1025       // Get subnetmask.
1026       //
1027       VarArg = VarArg->Next;
1028       if (VarArg == NULL) {
1029         ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_LACK_COMMAND), gShellNetwork1HiiHandle);
1030         ShellStatus = SHELL_INVALID_PARAMETER;
1031         goto ON_EXIT;
1032       }
1033 
1034       Status = NetLibStrToIp4 (VarArg->Arg, &ManualAddress.SubnetMask);
1035       if (EFI_ERROR(Status)) {
1036         ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_INVALID_IPADDRESS), gShellNetwork1HiiHandle, VarArg->Arg);
1037         ShellStatus = SHELL_INVALID_PARAMETER;
1038         goto ON_EXIT;
1039       }
1040 
1041       //
1042       // Get gateway.
1043       //
1044       VarArg = VarArg->Next;
1045       if (VarArg == NULL) {
1046         ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_LACK_COMMAND), gShellNetwork1HiiHandle);
1047         ShellStatus = SHELL_INVALID_PARAMETER;
1048         goto ON_EXIT;
1049       }
1050 
1051       Status = NetLibStrToIp4 (VarArg->Arg, &Gateway);
1052       if (EFI_ERROR(Status)) {
1053         ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_INVALID_IPADDRESS), gShellNetwork1HiiHandle, VarArg->Arg);
1054         ShellStatus = SHELL_INVALID_PARAMETER;
1055         goto ON_EXIT;
1056       }
1057 
1058       //
1059       // Set manual config policy.
1060       //
1061       Policy = Ip4Config2PolicyStatic;
1062       Status = IfCb->IfCfg->SetData (
1063                               IfCb->IfCfg,
1064                               Ip4Config2DataTypePolicy,
1065                               sizeof (EFI_IP4_CONFIG2_POLICY),
1066                               &Policy
1067                               );
1068       if (EFI_ERROR(Status)) {
1069         ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_AD), gShellNetwork1HiiHandle, L"ifconfig");
1070         ShellStatus = SHELL_ACCESS_DENIED;
1071         goto ON_EXIT;
1072       }
1073 
1074       //
1075       // Set Manual Address.
1076       //
1077       IsAddressOk = FALSE;
1078 
1079       Status = IfCb->IfCfg->RegisterDataNotify (
1080                               IfCb->IfCfg,
1081                               Ip4Config2DataTypeManualAddress,
1082                               MappedEvt
1083                               );
1084       if (EFI_ERROR (Status)) {
1085         ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_SET_ADDR_FAILED), gShellNetwork1HiiHandle, Status);
1086         ShellStatus = SHELL_ACCESS_DENIED;
1087         goto ON_EXIT;
1088       }
1089 
1090       DataSize = sizeof (EFI_IP4_CONFIG2_MANUAL_ADDRESS);
1091 
1092       Status = IfCb->IfCfg->SetData (
1093                               IfCb->IfCfg,
1094                               Ip4Config2DataTypeManualAddress,
1095                               DataSize,
1096                               &ManualAddress
1097                               );
1098 
1099       if (Status == EFI_NOT_READY) {
1100         gBS->SetTimer (TimeOutEvt, TimerRelative, 50000000);
1101 
1102         while (EFI_ERROR (gBS->CheckEvent (TimeOutEvt))) {
1103           if (IsAddressOk) {
1104             Status = EFI_SUCCESS;
1105             break;
1106           }
1107         }
1108       }
1109 
1110       IfCb->IfCfg->UnregisterDataNotify (
1111                      IfCb->IfCfg,
1112                      Ip4Config2DataTypeManualAddress,
1113                      MappedEvt
1114                      );
1115 
1116       if (EFI_ERROR (Status)) {
1117         ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_SET_ADDR_FAILED), gShellNetwork1HiiHandle, Status);
1118         ShellStatus = SHELL_ACCESS_DENIED;
1119         goto ON_EXIT;
1120       }
1121 
1122       //
1123       // Set gateway.
1124       //
1125       DataSize = sizeof (EFI_IPv4_ADDRESS);
1126 
1127       Status = IfCb->IfCfg->SetData (
1128                               IfCb->IfCfg,
1129                               Ip4Config2DataTypeGateway,
1130                               DataSize,
1131                               &Gateway
1132                               );
1133       if (EFI_ERROR (Status)) {
1134         ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_SET_ADDR_FAILED), gShellNetwork1HiiHandle, Status);
1135         ShellStatus = SHELL_ACCESS_DENIED;
1136         goto ON_EXIT;
1137       }
1138 
1139       VarArg = VarArg->Next;
1140 
1141     } else if (StrCmp (VarArg->Arg, L"dns") == 0) {
1142       //
1143       // Get DNS addresses.
1144       //
1145       VarArg = VarArg->Next;
1146       Tmp    = VarArg;
1147       Index  = 0;
1148       while (Tmp != NULL) {
1149         Index ++;
1150         Tmp = Tmp->Next;
1151       }
1152 
1153       Dns   = AllocatePool (Index * sizeof (EFI_IPv4_ADDRESS));
1154       ASSERT(Dns != NULL);
1155       Tmp   = VarArg;
1156       Index = 0;
1157       while (Tmp != NULL) {
1158         Status = NetLibStrToIp4 (Tmp->Arg, Dns + Index);
1159         if (EFI_ERROR(Status)) {
1160           ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_INVALID_IPADDRESS), gShellNetwork1HiiHandle, Tmp->Arg);
1161           ShellStatus = SHELL_INVALID_PARAMETER;
1162           goto ON_EXIT;
1163         }
1164         Index ++;
1165         Tmp = Tmp->Next;
1166       }
1167 
1168       VarArg = Tmp;
1169 
1170       //
1171       // Set DNS addresses.
1172       //
1173       DataSize = Index * sizeof (EFI_IPv4_ADDRESS);
1174 
1175       Status = IfCb->IfCfg->SetData (
1176                               IfCb->IfCfg,
1177                               Ip4Config2DataTypeDnsServer,
1178                               DataSize,
1179                               Dns
1180                               );
1181       if (EFI_ERROR (Status)) {
1182         ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_AD), gShellNetwork1HiiHandle, L"ifconfig");
1183         ShellStatus = SHELL_ACCESS_DENIED;
1184         goto ON_EXIT;
1185       }
1186     }
1187   }
1188 
1189 ON_EXIT:
1190   if (Dns != NULL) {
1191     FreePool (Dns);
1192   }
1193 
1194   return ShellStatus;
1195 
1196 }
1197 
1198 /**
1199   The ifconfig command main process.
1200 
1201   @param[in]   Private    The pointer of IFCONFIG_PRIVATE_DATA.
1202 
1203   @retval SHELL_SUCCESS  ifconfig command processed successfully.
1204   @retval others         The ifconfig command process failed.
1205 
1206 **/
1207 SHELL_STATUS
IfConfig(IN IFCONFIG_PRIVATE_DATA * Private)1208 IfConfig (
1209   IN IFCONFIG_PRIVATE_DATA    *Private
1210   )
1211 {
1212   EFI_STATUS    Status;
1213   SHELL_STATUS  ShellStatus;
1214 
1215   ShellStatus = SHELL_SUCCESS;
1216 
1217   //
1218   // Get configure information of all interfaces.
1219   //
1220   Status = IfConfigGetInterfaceInfo (
1221              Private->IfName,
1222              &Private->IfList
1223              );
1224   if (EFI_ERROR (Status)) {
1225     ShellStatus = SHELL_NOT_FOUND;
1226     goto ON_EXIT;
1227   }
1228 
1229   switch (Private->OpCode) {
1230   case IfConfigOpList:
1231     ShellStatus = IfConfigShowInterfaceInfo (&Private->IfList);
1232     break;
1233 
1234   case IfConfigOpClear:
1235     ShellStatus = IfConfigClearInterfaceInfo (&Private->IfList);
1236     break;
1237 
1238   case IfConfigOpSet:
1239     ShellStatus = IfConfigSetInterfaceInfo (&Private->IfList, Private->VarArg);
1240     break;
1241 
1242   default:
1243     ShellStatus = SHELL_UNSUPPORTED;
1244   }
1245 
1246 ON_EXIT:
1247   return ShellStatus;
1248 }
1249 
1250 /**
1251   The ifconfig command cleanup process, free the allocated memory.
1252 
1253   @param[in]   Private    The pointer of  IFCONFIG_PRIVATE_DATA.
1254 
1255 **/
1256 VOID
IfConfigCleanup(IN IFCONFIG_PRIVATE_DATA * Private)1257 IfConfigCleanup (
1258   IN IFCONFIG_PRIVATE_DATA  *Private
1259   )
1260 {
1261   LIST_ENTRY                *Entry;
1262   LIST_ENTRY                *NextEntry;
1263   IFCONFIG_INTERFACE_CB     *IfCb;
1264   ARG_LIST                  *ArgNode;
1265   ARG_LIST                  *ArgHead;
1266 
1267   ASSERT (Private != NULL);
1268 
1269   //
1270   // Clean the list which save the set config Args.
1271   //
1272   if (Private->VarArg != NULL) {
1273     ArgHead = Private->VarArg;
1274 
1275     while (ArgHead->Next != NULL) {
1276       ArgNode = ArgHead->Next;
1277       FreePool (ArgHead);
1278       ArgHead = ArgNode;
1279     }
1280 
1281     FreePool (ArgHead);
1282   }
1283 
1284   if (Private->IfName != NULL) {
1285     FreePool (Private->IfName);
1286   }
1287 
1288   //
1289   // Clean the IFCONFIG_INTERFACE_CB list.
1290   //
1291   NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Private->IfList) {
1292     IfCb = NET_LIST_USER_STRUCT (Entry, IFCONFIG_INTERFACE_CB, Link);
1293 
1294     RemoveEntryList (&IfCb->Link);
1295 
1296     if (IfCb->IfInfo != NULL) {
1297 
1298       FreePool (IfCb->IfInfo);
1299     }
1300 
1301     FreePool (IfCb);
1302   }
1303 
1304   FreePool (Private);
1305 }
1306 
1307 /**
1308   Function for 'ifconfig' command.
1309 
1310   @param[in] ImageHandle  Handle to the Image (NULL if Internal).
1311   @param[in] SystemTable  Pointer to the System Table (NULL if Internal).
1312 
1313   @retval EFI_SUCCESS    ifconfig command processed successfully.
1314   @retval others         The ifconfig command process failed.
1315 
1316 **/
1317 SHELL_STATUS
1318 EFIAPI
ShellCommandRunIfconfig(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)1319 ShellCommandRunIfconfig (
1320   IN EFI_HANDLE        ImageHandle,
1321   IN EFI_SYSTEM_TABLE  *SystemTable
1322   )
1323 {
1324   EFI_STATUS                Status;
1325   IFCONFIG_PRIVATE_DATA     *Private;
1326   LIST_ENTRY                *ParamPackage;
1327   SHELL_STATUS              ShellStatus;
1328   CONST CHAR16              *ValueStr;
1329   ARG_LIST                  *ArgList;
1330   CHAR16                    *ProblemParam;
1331   CHAR16                    *Str;
1332 
1333   Status = EFI_INVALID_PARAMETER;
1334   Private = NULL;
1335   ShellStatus = SHELL_SUCCESS;
1336 
1337   Status = ShellCommandLineParseEx (mIfConfigCheckList, &ParamPackage, &ProblemParam, TRUE, FALSE);
1338   if (EFI_ERROR (Status)) {
1339     if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
1340       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellNetwork1HiiHandle, L"ifconfig", ProblemParam);
1341       FreePool(ProblemParam);
1342       ShellStatus = SHELL_INVALID_PARAMETER;
1343     } else {
1344       ASSERT(FALSE);
1345     }
1346 
1347     goto ON_EXIT;
1348   }
1349 
1350   //
1351   // To handle unsupported option.
1352   //
1353   if (ShellCommandLineGetFlag (ParamPackage, L"-c")) {
1354     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_UNSUPPORTED_OPTION), gShellNetwork1HiiHandle,L"-c");
1355     ShellStatus = SHELL_INVALID_PARAMETER;
1356     goto ON_EXIT;
1357   }
1358 
1359   //
1360   // To handle no option.
1361   //
1362   if (!ShellCommandLineGetFlag (ParamPackage, L"-r") && !ShellCommandLineGetFlag (ParamPackage, L"-s") &&
1363       !ShellCommandLineGetFlag (ParamPackage, L"-l")) {
1364     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_LACK_OPTION), gShellNetwork1HiiHandle);
1365     ShellStatus = SHELL_INVALID_PARAMETER;
1366     goto ON_EXIT;
1367   }
1368 
1369   //
1370   // To handle conflict options.
1371   //
1372   if (((ShellCommandLineGetFlag (ParamPackage, L"-r")) && (ShellCommandLineGetFlag (ParamPackage, L"-s"))) ||
1373       ((ShellCommandLineGetFlag (ParamPackage, L"-r")) && (ShellCommandLineGetFlag (ParamPackage, L"-l"))) ||
1374       ((ShellCommandLineGetFlag (ParamPackage, L"-s")) && (ShellCommandLineGetFlag (ParamPackage, L"-l")))) {
1375     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_CON), gShellNetwork1HiiHandle, L"ifconfig");
1376     ShellStatus = SHELL_INVALID_PARAMETER;
1377     goto ON_EXIT;
1378   }
1379 
1380   Private = AllocateZeroPool (sizeof (IFCONFIG_PRIVATE_DATA));
1381   if (Private == NULL) {
1382     ShellStatus = SHELL_OUT_OF_RESOURCES;
1383     goto ON_EXIT;
1384   }
1385 
1386   InitializeListHead (&Private->IfList);
1387 
1388   //
1389   // To get interface name for the list option.
1390   //
1391   if (ShellCommandLineGetFlag (ParamPackage, L"-l")) {
1392     Private->OpCode = IfConfigOpList;
1393     ValueStr = ShellCommandLineGetValue (ParamPackage, L"-l");
1394     if (ValueStr != NULL) {
1395       Str = AllocateCopyPool (StrSize (ValueStr), ValueStr);
1396       ASSERT (Str != NULL);
1397       Private->IfName = Str;
1398     }
1399   }
1400 
1401   //
1402   // To get interface name for the clear option.
1403   //
1404   if (ShellCommandLineGetFlag (ParamPackage, L"-r")) {
1405     Private->OpCode = IfConfigOpClear;
1406     ValueStr = ShellCommandLineGetValue (ParamPackage, L"-r");
1407     if (ValueStr != NULL) {
1408       Str = AllocateCopyPool (StrSize (ValueStr), ValueStr);
1409       ASSERT (Str != NULL);
1410       Private->IfName = Str;
1411     }
1412   }
1413 
1414   //
1415   // To get interface name and corresponding Args for the set option.
1416   //
1417   if (ShellCommandLineGetFlag (ParamPackage, L"-s")) {
1418     ValueStr = ShellCommandLineGetValue (ParamPackage, L"-s");
1419     if (ValueStr == NULL) {
1420       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_LACK_INTERFACE), gShellNetwork1HiiHandle);
1421       ShellStatus = SHELL_INVALID_PARAMETER;
1422       goto ON_EXIT;
1423     }
1424 
1425     //
1426     // To split the configuration into multi-section.
1427     //
1428     ArgList         = SplitStrToList (ValueStr, L' ');
1429     ASSERT (ArgList != NULL);
1430 
1431     Private->OpCode = IfConfigOpSet;
1432     Private->IfName = ArgList->Arg;
1433 
1434     Private->VarArg = ArgList->Next;
1435 
1436     if (Private->IfName == NULL || Private->VarArg == NULL) {
1437       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_LACK_COMMAND), gShellNetwork1HiiHandle);
1438       ShellStatus = SHELL_INVALID_PARAMETER;
1439       goto ON_EXIT;
1440     }
1441   }
1442 
1443   //
1444   // Main process of ifconfig.
1445   //
1446   ShellStatus = IfConfig (Private);
1447 
1448 ON_EXIT:
1449 
1450   ShellCommandLineFreeVarList (ParamPackage);
1451 
1452   if (Private != NULL) {
1453     IfConfigCleanup (Private);
1454   }
1455 
1456   return ShellStatus;
1457 }
1458