• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /** @file
2   Shell application for VLAN configuration.
3 
4   Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>
5 
6   This program and the accompanying materials
7   are licensed and made available under the terms and conditions of the BSD License
8   which accompanies this distribution.  The full text of the license may be found at
9   http://opensource.org/licenses/bsd-license.php.
10 
11   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13 
14 **/
15 
16 #include <Uefi.h>
17 
18 #include <Protocol/VlanConfig.h>
19 
20 #include <Library/UefiApplicationEntryPoint.h>
21 #include <Library/UefiLib.h>
22 #include <Library/ShellLib.h>
23 #include <Library/MemoryAllocationLib.h>
24 #include <Library/HiiLib.h>
25 #include <Library/UefiBootServicesTableLib.h>
26 #include <Library/UefiHiiServicesLib.h>
27 #include <Library/NetLib.h>
28 
29 //
30 // String token ID of VConfig command help message text.
31 //
32 GLOBAL_REMOVE_IF_UNREFERENCED EFI_STRING_ID mStringVConfigHelpTokenId = STRING_TOKEN (STR_VCONFIG_HELP);
33 
34 #define INVALID_NIC_INDEX   0xffff
35 #define INVALID_VLAN_ID     0xffff
36 
37 //
38 // This is the generated String package data for all .UNI files.
39 // This data array is ready to be used as input of HiiAddPackages() to
40 // create a packagelist (which contains Form packages, String packages, etc).
41 //
42 extern UINT8      VConfigStrings[];
43 
44 EFI_HANDLE        mImageHandle  = NULL;
45 EFI_HII_HANDLE    mHiiHandle    = NULL;
46 
47 SHELL_PARAM_ITEM  mParamList[] = {
48   {
49     L"-l",
50     TypeValue
51   },
52   {
53     L"-a",
54     TypeMaxValue
55   },
56   {
57     L"-d",
58     TypeValue
59   },
60   {
61     NULL,
62     TypeMax
63   }
64 };
65 
66 /**
67   Locate the network interface handle buffer.
68 
69   @param[out]  NumberOfHandles Pointer to the number of handles.
70   @param[out]  HandleBuffer    Pointer to the buffer to store the returned handles.
71 
72 **/
73 VOID
LocateNicHandleBuffer(OUT UINTN * NumberOfHandles,OUT EFI_HANDLE ** HandleBuffer)74 LocateNicHandleBuffer (
75   OUT UINTN                       *NumberOfHandles,
76   OUT EFI_HANDLE                  **HandleBuffer
77   )
78 {
79   EFI_STATUS  Status;
80 
81   *NumberOfHandles  = 0;
82   *HandleBuffer     = NULL;
83 
84   Status = gBS->LocateHandleBuffer (
85                   ByProtocol,
86                   &gEfiVlanConfigProtocolGuid,
87                   NULL,
88                   NumberOfHandles,
89                   HandleBuffer
90                   );
91   if (EFI_ERROR (Status)) {
92     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_LOCATE_FAIL), mHiiHandle, Status);
93   }
94 }
95 
96 /**
97   Extract the decimal index from the network interface name.
98 
99   @param[in]  Name           Name of the network interface.
100 
101   @retval INVALID_NIC_INDEX  Failed to extract the network interface index.
102   @return others             The network interface index.
103 
104 **/
105 UINTN
NicNameToIndex(IN CHAR16 * Name)106 NicNameToIndex (
107   IN CHAR16                   *Name
108   )
109 {
110   CHAR16  *Str;
111 
112   Str = Name + 3;
113   if ((StrnCmp (Name, L"eth", 3) != 0) || (*Str == 0)) {
114     return INVALID_NIC_INDEX;
115   }
116 
117   while (*Str != 0) {
118     if ((*Str < L'0') || (*Str > L'9')) {
119       return INVALID_NIC_INDEX;
120     }
121 
122     Str++;
123   }
124 
125   return (UINT16) StrDecimalToUintn (Name + 3);
126 }
127 
128 /**
129   Find network interface device handle by its name.
130 
131   @param[in]  Name           Name of the network interface.
132 
133   @retval NULL               Cannot find the network interface.
134   @return others             Handle of the network interface.
135 
136 **/
137 EFI_HANDLE
NicNameToHandle(IN CHAR16 * Name)138 NicNameToHandle (
139   IN CHAR16                   *Name
140   )
141 {
142   UINTN       NumberOfHandles;
143   EFI_HANDLE  *HandleBuffer;
144   UINTN       Index;
145   EFI_HANDLE  Handle;
146 
147   //
148   // Find all NIC handles.
149   //
150   LocateNicHandleBuffer (&NumberOfHandles, &HandleBuffer);
151   if (NumberOfHandles == 0) {
152     return NULL;
153   }
154 
155   Index = NicNameToIndex (Name);
156   if (Index >= NumberOfHandles) {
157     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_INVALID_IF), mHiiHandle, Name);
158     Handle = NULL;
159   } else {
160     Handle = HandleBuffer[Index];
161   }
162 
163   FreePool (HandleBuffer);
164   return Handle;
165 }
166 
167 /**
168   Open VlanConfig protocol from a handle.
169 
170   @param[in]  Handle         The handle to open the VlanConfig protocol.
171 
172   @return The VlanConfig protocol interface.
173 
174 **/
175 EFI_VLAN_CONFIG_PROTOCOL *
OpenVlanConfigProtocol(IN EFI_HANDLE Handle)176 OpenVlanConfigProtocol (
177   IN EFI_HANDLE                 Handle
178   )
179 {
180   EFI_VLAN_CONFIG_PROTOCOL  *VlanConfig;
181 
182   VlanConfig = NULL;
183   gBS->OpenProtocol (
184          Handle,
185          &gEfiVlanConfigProtocolGuid,
186          (VOID **) &VlanConfig,
187          mImageHandle,
188          Handle,
189          EFI_OPEN_PROTOCOL_GET_PROTOCOL
190          );
191 
192   return VlanConfig;
193 }
194 
195 /**
196   Close VlanConfig protocol of a handle.
197 
198   @param[in]  Handle         The handle to close the VlanConfig protocol.
199 
200 **/
201 VOID
CloseVlanConfigProtocol(IN EFI_HANDLE Handle)202 CloseVlanConfigProtocol (
203   IN EFI_HANDLE                 Handle
204   )
205 {
206   gBS->CloseProtocol (
207          Handle,
208          &gEfiVlanConfigProtocolGuid,
209          mImageHandle,
210          Handle
211          );
212 }
213 
214 /**
215   Display VLAN configuration of a network interface.
216 
217   @param[in]  Handle         Handle of the network interface.
218   @param[in]  NicIndex       Index of the network interface.
219 
220 **/
221 VOID
ShowNicVlanInfo(IN EFI_HANDLE Handle,IN UINTN NicIndex)222 ShowNicVlanInfo (
223   IN EFI_HANDLE              Handle,
224   IN UINTN                   NicIndex
225   )
226 {
227   CHAR16                    *MacStr;
228   EFI_STATUS                Status;
229   UINTN                     Index;
230   EFI_VLAN_CONFIG_PROTOCOL  *VlanConfig;
231   UINT16                    NumberOfVlan;
232   EFI_VLAN_FIND_DATA        *VlanData;
233 
234   VlanConfig = OpenVlanConfigProtocol (Handle);
235   if (VlanConfig == NULL) {
236     return ;
237   }
238 
239   MacStr  = NULL;
240   Status  = NetLibGetMacString (Handle, mImageHandle, &MacStr);
241   if (EFI_ERROR (Status)) {
242     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_MAC_FAIL), mHiiHandle, Status);
243     goto Exit;
244   }
245 
246   ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_ETH_MAC), mHiiHandle, NicIndex, MacStr);
247 
248   Status = VlanConfig->Find (VlanConfig, NULL, &NumberOfVlan, &VlanData);
249   if (EFI_ERROR (Status)) {
250     if (Status == EFI_NOT_FOUND) {
251       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_NO_VLAN), mHiiHandle);
252     } else {
253       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_FIND_FAIL), mHiiHandle, Status);
254     }
255 
256     goto Exit;
257   }
258 
259   for (Index = 0; Index < NumberOfVlan; Index++) {
260     ShellPrintHiiEx (
261       -1,
262       -1,
263       NULL,
264       STRING_TOKEN (STR_VCONFIG_VLAN_DISPLAY),
265       mHiiHandle,
266       VlanData[Index].VlanId,
267       VlanData[Index].Priority
268       );
269   }
270 
271   FreePool (VlanData);
272 
273 Exit:
274   CloseVlanConfigProtocol (Handle);
275 
276   if (MacStr != NULL) {
277     FreePool (MacStr);
278   }
279 }
280 
281 /**
282   Display the VLAN configuration of all, or a specified network interface.
283 
284   @param[in]  Name           Name of the network interface. If NULL, the VLAN
285                              configuration of all network will be displayed.
286 
287 **/
288 VOID
DisplayVlan(IN CHAR16 * Name OPTIONAL)289 DisplayVlan (
290   IN CHAR16              *Name OPTIONAL
291   )
292 {
293   UINTN       NumberOfHandles;
294   EFI_HANDLE  *HandleBuffer;
295   UINTN       Index;
296   EFI_HANDLE  NicHandle;
297 
298   if (Name != NULL) {
299     //
300     // Display specified NIC
301     //
302     NicHandle = NicNameToHandle (Name);
303     if (NicHandle == NULL) {
304       return ;
305     }
306 
307     ShowNicVlanInfo (NicHandle, 0);
308     return ;
309   }
310 
311   //
312   // Find all NIC handles
313   //
314   LocateNicHandleBuffer (&NumberOfHandles, &HandleBuffer);
315   if (NumberOfHandles == 0) {
316     return ;
317   }
318 
319   for (Index = 0; Index < NumberOfHandles; Index++) {
320     ShowNicVlanInfo (HandleBuffer[Index], Index);
321   }
322 
323   FreePool (HandleBuffer);
324 }
325 
326 /**
327   Convert a NULL-terminated unicode decimal VLAN ID string to VLAN ID.
328 
329   @param[in]  String       Pointer to VLAN ID string from user input.
330 
331   @retval Value translated from String, or INVALID_VLAN_ID is string is invalid.
332 
333 **/
334 UINT16
StrToVlanId(IN CHAR16 * String)335 StrToVlanId (
336   IN CHAR16             *String
337   )
338 {
339   CHAR16  *Str;
340 
341   if (String == NULL) {
342     return INVALID_VLAN_ID;
343   }
344 
345   Str = String;
346   while ((*Str >= '0') && (*Str <= '9')) {
347     Str++;
348   }
349 
350   if (*Str != 0) {
351     return INVALID_VLAN_ID;
352   }
353 
354   return (UINT16) StrDecimalToUintn (String);
355 }
356 
357 /**
358   Add a VLAN device.
359 
360   @param[in]  ParamStr       Parameter string from user input.
361 
362 **/
363 VOID
AddVlan(IN CHAR16 * ParamStr)364 AddVlan (
365   IN CHAR16             *ParamStr
366   )
367 {
368   CHAR16                    *Name;
369   CHAR16                    *VlanIdStr;
370   CHAR16                    *PriorityStr;
371   CHAR16                    *StrPtr;
372   BOOLEAN                   IsSpace;
373   UINTN                     VlanId;
374   UINTN                     Priority;
375   EFI_HANDLE                Handle;
376   EFI_HANDLE                VlanHandle;
377   EFI_VLAN_CONFIG_PROTOCOL  *VlanConfig;
378   EFI_STATUS                Status;
379 
380   VlanConfig  = NULL;
381   Priority    = 0;
382 
383   if (ParamStr == NULL) {
384     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_NO_IF), mHiiHandle);
385     return ;
386   }
387 
388   StrPtr = AllocateCopyPool (StrSize (ParamStr), ParamStr);
389   if (StrPtr == NULL) {
390     return ;
391   }
392 
393   Name        = StrPtr;
394   VlanIdStr   = NULL;
395   PriorityStr = NULL;
396   IsSpace     = FALSE;
397   while (*StrPtr != 0) {
398     if (*StrPtr == L' ') {
399       *StrPtr = 0;
400       IsSpace = TRUE;
401     } else {
402       if (IsSpace) {
403         //
404         // Start of a parameter.
405         //
406         if (VlanIdStr == NULL) {
407           //
408           // 2nd parameter is VLAN ID.
409           //
410           VlanIdStr = StrPtr;
411         } else if (PriorityStr == NULL) {
412           //
413           // 3rd parameter is Priority.
414           //
415           PriorityStr = StrPtr;
416         } else {
417           //
418           // Ignore else parameters.
419           //
420           break;
421         }
422       }
423 
424       IsSpace = FALSE;
425     }
426 
427     StrPtr++;
428   }
429 
430   Handle = NicNameToHandle (Name);
431   if (Handle == NULL) {
432     goto Exit;
433   }
434 
435   VlanConfig = OpenVlanConfigProtocol (Handle);
436   if (VlanConfig == NULL) {
437     goto Exit;
438   }
439 
440   //
441   // Check VLAN ID.
442   //
443   if ((VlanIdStr == NULL) || (*VlanIdStr == 0)) {
444     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_NO_VID), mHiiHandle);
445     goto Exit;
446   }
447 
448   VlanId = StrToVlanId (VlanIdStr);
449   if (VlanId > 4094) {
450     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_INVALID_VID), mHiiHandle, VlanIdStr);
451     goto Exit;
452   }
453 
454   //
455   // Check Priority.
456   //
457   if ((PriorityStr != NULL) && (*PriorityStr != 0)) {
458     Priority = StrDecimalToUintn (PriorityStr);
459     if (Priority > 7) {
460       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_INVALID_PRIORITY), mHiiHandle, PriorityStr);
461       goto Exit;
462     }
463   }
464 
465   //
466   // Set VLAN
467   //
468   Status = VlanConfig->Set (VlanConfig, (UINT16) VlanId, (UINT8) Priority);
469   if (EFI_ERROR (Status)) {
470     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_SET_FAIL), mHiiHandle, Status);
471     goto Exit;
472   }
473 
474   //
475   // Connect the VLAN device.
476   //
477   VlanHandle = NetLibGetVlanHandle (Handle, (UINT16) VlanId);
478   if (VlanHandle != NULL) {
479     gBS->ConnectController (VlanHandle, NULL, NULL, TRUE);
480   }
481 
482   ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_SET_SUCCESS), mHiiHandle);
483 
484 Exit:
485   if (VlanConfig != NULL) {
486     CloseVlanConfigProtocol (Handle);
487   }
488 
489   FreePool (Name);
490 }
491 
492 /**
493   Remove a VLAN device.
494 
495   @param[in]  ParamStr       Parameter string from user input.
496 
497 **/
498 VOID
DeleteVlan(IN CHAR16 * ParamStr)499 DeleteVlan (
500   IN CHAR16 *ParamStr
501   )
502 {
503   CHAR16                    *Name;
504   CHAR16                    *VlanIdStr;
505   CHAR16                    *StrPtr;
506   UINTN                     VlanId;
507   EFI_HANDLE                Handle;
508   EFI_VLAN_CONFIG_PROTOCOL  *VlanConfig;
509   EFI_STATUS                Status;
510   UINT16                    NumberOfVlan;
511   EFI_VLAN_FIND_DATA        *VlanData;
512 
513   VlanConfig = NULL;
514 
515   if (ParamStr == NULL) {
516     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_NO_IF), mHiiHandle);
517     return ;
518   }
519 
520   StrPtr = AllocateCopyPool (StrSize (ParamStr), ParamStr);
521   if (StrPtr == NULL) {
522     return ;
523   }
524 
525   Name      = StrPtr;
526   VlanIdStr = NULL;
527   while (*StrPtr != 0) {
528     if (*StrPtr == L'.') {
529       *StrPtr   = 0;
530       VlanIdStr = StrPtr + 1;
531       break;
532     }
533 
534     StrPtr++;
535   }
536 
537   Handle = NicNameToHandle (Name);
538   if (Handle == NULL) {
539     goto Exit;
540   }
541 
542   VlanConfig = OpenVlanConfigProtocol (Handle);
543   if (VlanConfig == NULL) {
544     goto Exit;
545   }
546 
547   //
548   // Check VLAN ID
549   //
550   if (VlanIdStr == NULL || *VlanIdStr == 0) {
551     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_NO_VID), mHiiHandle);
552     goto Exit;
553   }
554 
555   VlanId = StrToVlanId (VlanIdStr);
556   if (VlanId > 4094) {
557     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_INVALID_VID), mHiiHandle, VlanIdStr);
558     goto Exit;
559   }
560 
561   //
562   // Delete VLAN.
563   //
564   Status = VlanConfig->Remove (VlanConfig, (UINT16) VlanId);
565   if (EFI_ERROR (Status)) {
566     if (Status == EFI_NOT_FOUND) {
567       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_NOT_FOUND), mHiiHandle);
568     } else {
569       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_REMOVE_FAIL), mHiiHandle, Status);
570     }
571 
572     goto Exit;
573   }
574 
575   //
576   // Check whether this is the last VLAN to remove.
577   //
578   Status = VlanConfig->Find (VlanConfig, NULL, &NumberOfVlan, &VlanData);
579   if (EFI_ERROR (Status)) {
580     //
581     // This is the last VLAN to remove, try to connect the controller handle.
582     //
583     gBS->ConnectController (Handle, NULL, NULL, TRUE);
584   } else {
585     FreePool (VlanData);
586   }
587 
588   ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_REMOVE_SUCCESS), mHiiHandle);
589 
590 Exit:
591   if (VlanConfig != NULL) {
592     CloseVlanConfigProtocol (Handle);
593   }
594 
595   FreePool (Name);
596 }
597 
598 /**
599   The actual entry point for the application.
600 
601   @param[in] ImageHandle    The firmware allocated handle for the EFI image.
602   @param[in] SystemTable    A pointer to the EFI System Table.
603 
604   @retval EFI_SUCCESS       The entry point executed successfully.
605   @retval other             Some error occur when executing this entry point.
606 
607 **/
608 EFI_STATUS
609 EFIAPI
VlanConfigMain(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)610 VlanConfigMain (
611   IN EFI_HANDLE        ImageHandle,
612   IN EFI_SYSTEM_TABLE  *SystemTable
613   )
614 {
615   LIST_ENTRY    *List;
616   CONST CHAR16  *Str;
617   EFI_HII_PACKAGE_LIST_HEADER     *PackageList;
618   EFI_STATUS    Status;
619 
620   mImageHandle = ImageHandle;
621 
622   //
623   // Retrieve HII package list from ImageHandle
624   //
625   Status = gBS->OpenProtocol (
626                   ImageHandle,
627                   &gEfiHiiPackageListProtocolGuid,
628                   (VOID **) &PackageList,
629                   ImageHandle,
630                   NULL,
631                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
632                   );
633   if (EFI_ERROR (Status)) {
634     return Status;
635   }
636 
637   //
638   // Publish HII package list to HII Database.
639   //
640   Status = gHiiDatabase->NewPackageList (
641                           gHiiDatabase,
642                           PackageList,
643                           NULL,
644                           &mHiiHandle
645                           );
646   if (EFI_ERROR (Status)) {
647     return Status;
648   }
649 
650   if (mHiiHandle == NULL) {
651     return EFI_SUCCESS;
652   }
653 
654   List = NULL;
655   ShellCommandLineParseEx (mParamList, &List, NULL, FALSE, FALSE);
656   if (List == NULL) {
657     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_NO_ARG), mHiiHandle);
658     goto Exit;
659   }
660 
661   if (ShellCommandLineGetFlag (List, L"-l")) {
662     Str = ShellCommandLineGetValue (List, L"-l");
663     DisplayVlan ((CHAR16 *) Str);
664     goto Exit;
665   }
666 
667   if (ShellCommandLineGetFlag (List, L"-a")) {
668     Str = ShellCommandLineGetValue (List, L"-a");
669     AddVlan ((CHAR16 *) Str);
670     goto Exit;
671   }
672 
673   if (ShellCommandLineGetFlag (List, L"-d")) {
674     Str = ShellCommandLineGetValue (List, L"-d");
675     DeleteVlan ((CHAR16 *) Str);
676     goto Exit;
677   }
678 
679   //
680   // No valid argument till now.
681   //
682   ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VCONFIG_NO_ARG), mHiiHandle);
683 
684 Exit:
685   if (List != NULL) {
686     ShellCommandLineFreeVarList (List);
687   }
688 
689   //
690   // Remove our string package from HII database.
691   //
692   HiiRemovePackages (mHiiHandle);
693 
694   return EFI_SUCCESS;
695 }
696